diff --git a/content/chainguard/checks/run-checks.md b/content/chainguard/checks/run-checks.md index ccd2cfabd9..7a72f82caa 100644 --- a/content/chainguard/checks/run-checks.md +++ b/content/chainguard/checks/run-checks.md @@ -72,7 +72,7 @@ If you name a skipped check, as in `run-ci deploy`, or if `run-ci` skips every c Because of these differences, a pass from `run-ci` predicts that the pull request's checks will pass, but only the pull request's run in fresh VMs decides what GitHub shows. -The `run-ci` command works while something is attached to the session, such as your terminal. It also works after you detach, if you keep the session running with a **Detach — keep running** option or `--keep`, as described in [Keep a session running while you're away](/chainguard/workspaces/manage-sessions/#keep-a-session-running-while-youre-away). Running checks doesn't keep a session from parking, so if the session parks while `run-ci` runs, the run stops and `run-ci` exits with `2`. +The `run-ci` command works while something is attached to the session, such as your terminal. It also works after you detach, while the session keeps running, as described in [Keep a session running while you're away](/chainguard/workspaces/manage-sessions/#keep-a-session-running-while-youre-away). A run keeps the session busy, so the session doesn't park while the run is in progress, up to 24 hours after you last detach. While it runs, `chainctl develop list` shows `busy: check run` in the session's state. In a session created with `--keep park` or with `chainctl` 0.2.382 or earlier, or while your organization's monthly compute allowance is used up, running checks doesn't keep the session from parking. If the session parks while `run-ci` runs, the run stops and `run-ci` exits with `2`. Only one `run-ci` or `chainctl develop check` can run in a session at a time. One that starts while another runs fails and tells you to wait for the first to finish. @@ -92,7 +92,7 @@ chainctl develop check $SESSION --check test --parent $ORGANIZATION The command uses the same runner as `run-ci` and streams each step's output. It skips the same checks as `run-ci`, and prints a line for each, such as `Skipped deploy: declares identity gcp-prod, which only CI provides`. It exits with `0` when the checks pass, or `1` when a check fails or the checks can't run, including when you name a skipped check with `--check`. To print the result as JSON, add `--output json`. The JSON lists the checks it skipped under `skipped`. -If you detached from the session and kept it running, `chainctl develop check` might fail with a message that says `the guest is held by another controller`. Run the command again, or attach to the session and run `run-ci` in it. +If you detached from the session and it's still running, `chainctl develop check` might fail with a message that says `the guest is held by another controller`. Run the command again, or attach to the session and run `run-ci` in it. ## Validate your configuration offline {#validate-your-configuration-offline} diff --git a/content/chainguard/workspaces/chainctl-develop-reference.md b/content/chainguard/workspaces/chainctl-develop-reference.md index 4edae53942..b0d8662009 100644 --- a/content/chainguard/workspaces/chainctl-develop-reference.md +++ b/content/chainguard/workspaces/chainctl-develop-reference.md @@ -34,6 +34,7 @@ The examples on this page use `$ORGANIZATION` for the name of your Chainguard or | [`chainctl develop check`](#chainctl-develop-check) | Runs your repository's checks in a session. | | [`chainctl develop creds`](#chainctl-develop-creds) | Shows or changes what a session can reach. | | [`chainctl develop github`](#chainctl-develop-github) | Connects your GitHub account to the sessions you create. | +| [`chainctl develop claude`](#chainctl-develop-claude) | Lets Chainguard hold a Claude login for your sessions. | | [`chainctl develop policy`](#chainctl-develop-policy) | Shows or changes your organization's GitHub policy for sessions. | | [`chainctl develop init`](#chainctl-develop-init) | Signs you up and turns on Chainguard Checks and Chainguard Workspaces. | | [`chainctl develop accept-terms`](#chainctl-develop-accept-terms) | Accepts the terms that Chainguard Workspaces is offered under. | @@ -76,11 +77,11 @@ The argument is a directory, a repository URL, or a session. Without one, `chain | `--check` | Gives a new session the environment and network access of a check. From a local directory, the check must be in `.chainguard/ci.yaml`. From a repository URL, it can also be in the `.chainguard/ci/` directory. Refer to [How a session chooses its environment](/chainguard/workspaces/session-environment/#how-a-session-chooses-its-environment). | | `--cache` | For a session opened from a repository URL, mounts the Go build cache that your checks keep for your default branch. Refer to [Start with a warm Go build cache](/chainguard/workspaces/session-environment/#start-with-a-warm-go-build-cache). | | `--with` | Gives a new or existing session access beyond its defaults. Repeat the flag or separate entries with commas. Refer to [Allow access ahead of time](/chainguard/workspaces/credentials/#allow-access-ahead-of-time) for the entries. | -| `--keep` | Keeps the session running when you detach, for a duration of up to `24h`, such as `8h`. With `always`, creates a session that keeps running instead of parking. Refer to [Keep a session running while you're away](/chainguard/workspaces/manage-sessions/#keep-a-session-running-while-youre-away). | +| `--keep` | Sets how the session keeps running when you detach. Without it, a new session keeps running while it's busy and parks after it's been idle for 10 minutes, no later than 24 hours after you last detach. A duration of up to `24h`, such as `8h`, keeps the session running for that long when you detach. With `always`, creates a session that keeps running instead of parking. With `park`, creates a session that parks about 10 minutes after you detach, busy or not. Refer to [Keep a session running while you're away](/chainguard/workspaces/manage-sessions/#keep-a-session-running-while-youre-away). | | `--git-remote` | For a directory, the git remote whose GitHub repository a new session is on, or `-` for no repository. Refer to [Choose the session's repository](/chainguard/workspaces/manage-sessions/#choose-the-sessions-repository). | | `-o json` | Prints the session as JSON instead of attaching to it, and creates the session first if none matches. Refer to [Use sessions from scripts](/chainguard/workspaces/manage-sessions/#use-sessions-from-scripts). | -The `--name`, `--env`, `--check`, `--cache`, and `--keep always` flags each open a new session, so you don't need `--new` with them, and you can't combine them with a session name. +The `--name`, `--env`, `--check`, `--cache`, `--keep always`, and `--keep park` flags each open a new session, so you don't need `--new` with them, and you can't combine them with a session name. In a checkout of a repository named `app`, this example opens a new session named `app/scratch` with the default environment: @@ -170,7 +171,7 @@ Without flags, the command lists each service's source and bindings, what your l | Flag | Description | | ---- | ----------- | | `--revoke` | Takes an entry back from the session and from your laptop's remembered approvals. Repeatable. | -| `--source` | Sets where a service's credential comes from: `laptop`, `org`, or `off`. Repeatable. | +| `--source` | Sets where a service's credential comes from: `laptop`, `org`, `owner`, or `off`. Repeatable. | | `--forget` | Removes everything your laptop remembers for the session's repository, without changing the session. | To add access, run `chainctl develop SESSION --with ENTRY` instead. Refer to [Review and revoke a session's credentials](/chainguard/workspaces/credentials/#review-and-revoke-a-sessions-credentials) for the entries and sources that each service takes. @@ -197,6 +198,22 @@ chainctl develop github status [-o json|table] | `logout` | Disconnects your GitHub account. Sessions that act on GitHub as you refuse `git` and `gh` requests until you connect again. | | `status` | Shows your connected GitHub account, the app it's connected through, whether the connection works, whether your organization's policy allows sessions to act as you, and which accounts the checkout in your current directory still needs the app installed on. | +## chainctl develop claude {#chainctl-develop-claude} + +Lets Chainguard hold a Claude login for your sessions, so that Claude Code in them works whether or not you're attached. One login serves your sessions in every organization, except sessions that use Vertex AI. Refer to [Let Chainguard hold your Claude login](/chainguard/workspaces/coding-agents/#let-chainguard-hold-your-claude-login). + +``` +chainctl develop claude login [-o json] +chainctl develop claude status [-o json|table] +chainctl develop claude logout +``` + +| Command | What it does | +| ------- | ------------ | +| `login` | Opens your browser to log in to Claude, and asks you to paste the code that the page shows. Chainguard then holds the login for about 4 weeks. A new login replaces the earlier one and revokes it. | +| `status` | Shows the login's Claude account, its Claude organization, whether it still works, and when it ends, in the `CLAUDE ACCOUNT`, `ORGANIZATION`, `STATE`, and `EXPIRES` columns. | +| `logout` | Revokes the login at Anthropic, which ends it in every session at once, and has Chainguard forget it. Sessions that use it refuse Claude Code's requests until you log in again. If Chainguard can't reach Anthropic, it keeps the login, and `logout` says so. In that case, run `chainctl develop claude logout` again. | + ## chainctl develop policy Shows or changes your organization's GitHub policy for sessions. Alias: `policies`. @@ -267,9 +284,11 @@ Each command accepts only the following output formats: | `creds` | `table` (default), `json` | `sources`, with each service's `source` and `bindings`; `serving`, what serves the session's laptop credentials; and `trail`, the latest changes. | | `github login` | `json` | The connected account, in the same form as `github status`. | | `github status` | `table` (default), `json` | `login`, `valid`, `user_github`, `installed_accounts`, and `app_slug`. | +| `claude login` | `json` | The login, in the same form as `claude status`. | +| `claude status` | `table` (default), `json` | `supported`, `enrolled`, `email`, `organization`, `organization_uuid`, `valid`, and `expires`. | | `policy describe`, `policy set` | `table` (default), `json` | The policy. | -A session in JSON output includes its `name`, such as `app/quiet-harbor`; its `label`, the name with the repository's GitHub owner in front; its `id` and `short_id`; its `state`, `repository`, `branch`, `head`, and `directory`; and timestamps such as `create_time` and `expire_time`. Fields without a value are left out. +A session in JSON output includes its `name`, such as `app/quiet-harbor`; its `label`, the name with the repository's GitHub owner in front; its `id` and `short_id`; its `state`, `repository`, `branch`, `head`, and `directory`; how it keeps running after you detach, in `idle` (`auto_hold` or `keep_running`), `keep_running_until`, `held_until`, and `last_busy`; and timestamps such as `create_time` and `expire_time`. Fields without a value are left out. ## Exit codes @@ -285,7 +304,7 @@ What you can do with `chainctl develop` depends on your role in the session's or | Commands | Roles | | -------- | ----- | -| `chainctl develop`, `list`, `rename`, `delete`, `check`, `creds`, `github`, and `policy describe` | `owner`, `limited_owner`, or `sandbox.user` | +| `chainctl develop`, `list`, `rename`, `delete`, `check`, `creds`, `github`, `claude`, and `policy describe` | `owner`, `limited_owner`, or `sandbox.user` | | `accept-terms` | `owner` or `limited_owner` | | `list --all` and `policy set` | `owner` | diff --git a/content/chainguard/workspaces/coding-agents.md b/content/chainguard/workspaces/coding-agents.md index a4feb2960b..e925cae71e 100644 --- a/content/chainguard/workspaces/coding-agents.md +++ b/content/chainguard/workspaces/coding-agents.md @@ -21,13 +21,14 @@ Claude Code is the only coding agent that sessions supply a model credential for ## Before you begin -Claude Code in a session uses the Claude credential from your laptop, so set it up there first: +Claude Code in a session uses a Claude credential from your laptop, or a Claude login that Chainguard holds for you. Set one up first: -1. Update `chainctl` to the [minimum version](/get-started/checks-and-workspaces/set-up/#install-or-update-chainctl) or later, as described in [Updating chainctl](/platform/chainctl-usage/how-to-install-chainctl/#updating-chainctl). Earlier versions don't send Claude's credential to a session. -2. Install Claude Code on your laptop, as described in the [Claude Code documentation](https://code.claude.com/docs/en/overview). -3. Run `claude` on your laptop and log in. +1. Update `chainctl` to the [minimum version](/get-started/checks-and-workspaces/set-up/#install-or-update-chainctl) or later, as described in [Updating chainctl](/platform/chainctl-usage/how-to-install-chainctl/#updating-chainctl). Releases before 0.2.383 can't use a Claude login that Chainguard holds, and releases before 0.2.382 don't send Claude's credential to a session. +2. Do one of the following: + - To let Chainguard hold a Claude login for your sessions, run `chainctl develop claude login`, as described in [Let Chainguard hold your Claude login](#let-chainguard-hold-your-claude-login). Claude Code then keeps working in a session while you're detached, and your laptop doesn't need Claude Code. This works only with the Anthropic API, not with Vertex AI. + - To use the credential from your laptop, install Claude Code on your laptop, as described in the [Claude Code documentation](https://code.claude.com/docs/en/overview), and then run `claude` on your laptop and log in. -When you attach to a session, `chainctl` sends the session's host the first credential it finds on your laptop, in this order: a `chainctl-credential-claude` credential helper on your `PATH`, the `ANTHROPIC_API_KEY` environment variable, an `apiKeyHelper` from your Claude Code settings, the `CLAUDE_CODE_OAUTH_TOKEN` environment variable, and your stored Claude login. Apart from the credential helper, this is the order Claude Code uses on your laptop. Both an API key and a Claude subscription login work. +When you attach to a session that uses your laptop's credential, `chainctl` sends the session's host the first credential it finds on your laptop, in this order: a `chainctl-credential-claude` credential helper on your `PATH`, the `ANTHROPIC_API_KEY` environment variable, an `apiKeyHelper` from your Claude Code settings, the `CLAUDE_CODE_OAUTH_TOKEN` environment variable, and your stored Claude login. Apart from the credential helper, this is the order Claude Code uses on your laptop. Both an API key and a Claude subscription login work. For a session that uses the Claude login Chainguard holds for you, `chainctl` sends nothing for Claude. Claude Code must also be installed in the session. The default environment includes it. If your session uses your repository's `.chainguard/develop.yaml` or `.chainguard/ci.yaml` file, add `claude` to that file's packages, as described in [Configure a session's environment](/chainguard/workspaces/session-environment/). @@ -39,9 +40,9 @@ Open a session, then run `claude` in it: claude ``` -Claude Code starts without asking you to log in. When you attach, `chainctl` sends your Claude credential to the session's host, outside the VM. Claude Code's requests go to `http://claude/` in the session, and the host sends them on with your credential. The host passes on only requests to the Claude API's messages and models endpoints, not its account or organization endpoints. For a stored Claude login, `chainctl` sends only the short-lived access token, never the refresh token. +Claude Code starts without asking you to log in. Your Claude credential is on the session's host, outside the VM: either `chainctl` sent it from your laptop when you attached, or Chainguard sent it from the Claude login it holds for you. Claude Code's requests go to `http://claude/` in the session, and the host sends them on with your credential. The host passes on only requests to the Claude API's messages and models endpoints, not its account or organization endpoints. For a stored Claude login, `chainctl` sends only the short-lived access token, never the refresh token. Likewise, for a login Chainguard holds, the host gets only short-lived access tokens, and the refresh token never leaves Chainguard. -If Claude Code in the session reports that the token sent to the session expired, attach to the session again so that `chainctl` sends a fresh one. If `chainctl` says that the Claude login on your laptop expired, run `claude` on your laptop once to refresh it. To keep a long task from stopping when a login expires, use a token from `claude setup-token`, as described in [Keep Claude Code working while you're away](#keep-claude-code-working-while-youre-away). For other errors, refer to [Claude Code reports an error in the session](/chainguard/workspaces/troubleshooting/#claude-code-reports-an-error-in-the-session). +If Claude Code in the session reports that the token sent to the session expired, attach to the session again so that `chainctl` sends a fresh one. If `chainctl` says that the Claude login on your laptop expired, run `claude` on your laptop once to refresh it. To keep a long task from stopping when a login expires, run `chainctl develop claude login`, as described in [Let Chainguard hold your Claude login](#let-chainguard-hold-your-claude-login). For other errors, refer to [Claude Code reports an error in the session](/chainguard/workspaces/troubleshooting/#claude-code-reports-an-error-in-the-session). ## Use Claude through Vertex AI {#use-claude-through-vertex-ai} @@ -62,9 +63,10 @@ When you create a session, `chainctl` chooses how Claude Code in it reaches Clau 1. If Claude Code on your laptop is set to use Vertex AI with `CLAUDE_CODE_USE_VERTEX`, the session uses Vertex AI with the project in `ANTHROPIC_VERTEX_PROJECT_ID` and the region in `CLOUD_ML_REGION`. 2. If you set `develop.vertex.project` in your `chainctl` configuration, the session uses Vertex AI in that project. 3. If Claude Code on your laptop has a Claude login or an API key, the session uses the Anthropic API. -4. If your Google Cloud application default credentials name a project, the session uses Vertex AI in that project. +4. If Chainguard holds a Claude login for you that still works, the session uses the Anthropic API, and `chainctl` prints `claude: the Anthropic API, from your Claude login held by Chainguard`. +5. If your Google Cloud application default credentials name a project, the session uses Vertex AI in that project. -If none of these applies, the session uses the Anthropic API, and Claude Code works once you log in to Claude on your laptop and attach again. +If none of these applies, the session uses the Anthropic API, and Claude Code works once you run `chainctl develop claude login`, or log in to Claude on your laptop, and attach again. `chainctl` reads `CLAUDE_CODE_USE_VERTEX` and the other Claude Code variables from the `env` of your Claude Code settings, then from your environment. If Claude Code uses Vertex AI but names no project, `chainctl` uses `develop.vertex.project`, then the project your Google Cloud credentials name, and refuses to create the session if it finds none. When a new session uses Vertex AI, `chainctl` says so and names where the project came from. @@ -73,7 +75,7 @@ If none of these applies, the session uses the Anthropic API, and Claude Code wo A session keeps its provider when it parks and resumes. To switch a running session between the Anthropic API and Vertex AI: 1. Press `Ctrl+]` to open the session menu, and choose **Credentials**. -2. Choose `claude`, then choose **Use Vertex AI…**, or **Use Anthropic…** on a session that uses Vertex AI. To use Vertex AI, your laptop needs Google Cloud application default credentials. +2. Choose `claude`, then choose **Use Vertex AI…**, or **Use Anthropic…** on a session that uses Vertex AI. To use Vertex AI, your laptop needs Google Cloud application default credentials, and the session must use your laptop's credential. If it uses the Claude login Chainguard holds for you, first choose **Set the source**, then **From the owner's laptop**. 3. Choose whether the change applies to this session only or to new sessions too. For Vertex AI, check the project and region first. For new sessions, `chainctl` saves the project and region in `develop.vertex.project` and `develop.vertex.region`, or clears them when you switch to the Anthropic API. 4. In the session, exit Claude Code with `/exit`, then run `claude --continue` to resume the conversation with the new provider. @@ -125,7 +127,7 @@ The session's managed settings allow only MCP servers reached over `https://`, a The [`cg-oci`](/platform/mcp-servers/cg-oci/) MCP server doesn't work in a session, because the session's requests to `cgr.dev` reach only the container registry. -## Choose a permission mode +## Choose a permission mode {#choose-a-permission-mode} Claude Code in a session starts in its default permission mode, so it asks you before it runs commands or edits files. @@ -143,30 +145,56 @@ A session has no credentials for services such as AWS, Azure, or a private packa ## Keep Claude Code working while you're away {#keep-claude-code-working-while-youre-away} -To leave Claude Code working in a session, detach and keep the session running, rather than letting it park: +When you detach, a session keeps running while Claude Code works on a turn, and parks after it's been idle for 10 minutes, no later than 24 hours after you last detach. To leave Claude Code working, press `Ctrl+]` to open the session menu, and then press `Enter` to choose **Detach — keep running while busy**. -1. Press `Ctrl+]` to open the session menu. -2. Choose **Detach — keep running 4h**, or **Detach — keep running for…** to set a duration of up to 24 hours. +Claude Code that waits at a permission prompt or for your input isn't busy, so the session can park while it waits for you. To let Claude Code work without asking, refer to [Choose a permission mode](#choose-a-permission-mode). To keep the session running whether or not it's busy, choose **Detach — keep running 4h**, or **Detach — keep running for…** to set a duration of up to 24 hours. For what counts as busy, refer to [Keep a session running while you're away](/chainguard/workspaces/manage-sessions/#keep-a-session-running-while-youre-away). -The session's host keeps the Claude credential that `chainctl` sent, so Claude Code keeps working after you close the terminal. How long it keeps working without a terminal depends on the credential: +Claude Code keeps working only while the session's host has a Claude credential that works. How long it keeps working without a terminal depends on the credential: | Credential | How long Claude Code keeps working | | ---------- | ---------------------------------- | +| Your Claude login held by Chainguard, from `chainctl develop claude login` | As long as the session runs, through parks and resumes, until the login ends after about 4 weeks or you run `chainctl develop claude logout`. | | An API key, the output of an `apiKeyHelper`, or `CLAUDE_CODE_OAUTH_TOKEN` | Until the session parks. | -| Your stored Claude login | Until the access token that `chainctl` sent expires. | -| A Google credential, for Vertex AI | Until the access token that `chainctl` sent expires, or until the session parks if `chainctl` sent your refresh token. | +| Your stored Claude login on your laptop | Until the access token that `chainctl` sent expires. | +| A Google credential, for Vertex AI | Until the session parks if `chainctl` sent your refresh token, which it does for a session that keeps running while it's busy and for one you keep running. Otherwise, until the access token that `chainctl` sent expires. | -When you attach, `chainctl` says which credential it sent and how long the session keeps it. The **Credentials** screen in the session menu shows the same. +When you attach, `chainctl` says which credential the session uses and how long the session keeps it. The **Credentials** screen in the session menu shows the same. -The terminal you detached from keeps serving the session, through sleep and network interruptions, until the session stops running, you press `Ctrl+C`, or you close the terminal. While it serves, it keeps the session's Claude credential current: it sends new Google access tokens, reruns your `apiKeyHelper`, and sends your stored login again each time Claude Code on your laptop refreshes it. If your stored login is about to expire without being refreshed, `chainctl` tells you to run `claude` on your laptop. +When the session parks, its host discards the credential. When the session resumes, Chainguard sends the host fresh access tokens from a Claude login it holds for you, even if you don't attach. `chainctl` sends a credential from your laptop again when you return. Either way, Claude Code is still running in the session, with its conversation intact. -For long unattended work with a Claude subscription, run `claude setup-token` on your laptop. In the shell where you run `chainctl develop`, set `CLAUDE_CODE_OAUTH_TOKEN` to the token it prints, and then attach. The session keeps that token until it parks. +For a task that runs longer than a day, create a session with `--keep always`. Refer to [Keep a session running while you're away](/chainguard/workspaces/manage-sessions/#keep-a-session-running-while-youre-away). + +### Let Chainguard hold your Claude login {#let-chainguard-hold-your-claude-login} + +To keep Claude Code working in your sessions while you're away, let Chainguard hold a Claude login for them. Run the following command on your laptop: + +```shell +chainctl develop claude login +``` + +`chainctl` opens your browser to log in to Claude, and prints the URL to visit if the browser doesn't open. After you log in, the page shows a code. Paste the code into your terminal. The whole login must finish within 5 minutes. Chainguard then holds the login and refreshes it, and your laptop stores no token. The login asks Anthropic only for inference, and Chainguard uses it only for Claude Code in your sessions. + +Chainguard sends the session's host short-lived access tokens from the login whether or not you're attached, so Claude Code keeps working for as long as the session runs. One login serves your sessions in every organization. Which sessions use it depends on the session: -When the session parks, its host discards the credential. When you return, `chainctl` sends it again, and Claude Code is still running in the session, with its conversation intact. +- A new session that uses the Anthropic API uses the login, even if your laptop has an API key or a Claude login. To keep your laptop's credential in a new session, create it with `--with claude`. +- A session that uses your laptop's credential by default switches to the login the next time you attach. A session whose `claude` source you set yourself keeps that source. +- A session that uses Vertex AI never uses the login. + +When you attach to a session that uses the login, `chainctl` prints `claude: served from your Claude login held by Chainguard (EMAIL), attached or not`, where `EMAIL` is your Claude account's email address. + +If Chainguard holds no Claude login that works for you, and you attach to a session that uses the Claude login stored on your laptop, `chainctl` asks whether to let Chainguard hold one. Answer `y` to log in. If you answer `n`, `chainctl` doesn't ask again on that laptop. Without a terminal, it prints a reminder to run `chainctl develop claude login` instead. + +The login lasts about 4 weeks. In its last 3 days, `chainctl` tells you when it ends each time you attach to a session. To renew it, run `chainctl develop claude login` again, which replaces the earlier login and revokes it. To see the login, run `chainctl develop claude status`. + +To end the login, run `chainctl develop claude logout`, which revokes it at Anthropic and ends it in every session at once. Claude Code in those sessions then fails until you log in again, or until you switch a session back to your laptop's credential with `chainctl develop creds`, as described in [Review and revoke a session's credentials](/chainguard/workspaces/credentials/#review-and-revoke-a-sessions-credentials). For each command, refer to [`chainctl develop claude`](/chainguard/workspaces/chainctl-develop-reference/#chainctl-develop-claude). + +### Keep a credential from your laptop working {#keep-a-credential-from-your-laptop-working} + +If you detach with **Detach — keep running 4h**, **Detach — keep running for…**, or a `--keep` duration, or from a session you're already keeping running, the terminal you detached from keeps serving the session, through sleep and network interruptions, until the session stops running, you press `Ctrl+C`, or you close the terminal. While it serves, it keeps the session's Claude credential current: it sends new Google access tokens, reruns your `apiKeyHelper`, and sends your stored login again each time Claude Code on your laptop refreshes it. If your stored login is about to expire without being refreshed, `chainctl` tells you to run `claude` on your laptop. While the terminal serves a detached session, it refuses new approval requests, so allow anything the agent will need ahead of time with `--with`. -For a task that runs longer than a day, create a session with `--keep always`. Refer to [Keep a session running while you're away](/chainguard/workspaces/manage-sessions/#keep-a-session-running-while-youre-away). +To keep Claude Code working unattended on a Claude subscription without letting Chainguard hold your login, run `claude setup-token` on your laptop. In the shell where you run `chainctl develop`, set `CLAUDE_CODE_OAUTH_TOKEN` to the token it prints, and then attach to a session that uses your laptop's credential. The session keeps that token until it parks. ## Run several agents in parallel {#run-several-agents-in-parallel} diff --git a/content/chainguard/workspaces/credentials.md b/content/chainguard/workspaces/credentials.md index 50a7bd5b2f..72d57dd172 100644 --- a/content/chainguard/workspaces/credentials.md +++ b/content/chainguard/workspaces/credentials.md @@ -4,7 +4,7 @@ linktitle: "Session credentials" description: "Learn how a Chainguard Workspaces session reaches GitHub, Claude, and Chainguard without holding credentials, and how to approve, review, and revoke what it can reach." type: "article" date: 2026-10-08T00:00:00+00:00 -lastmod: 2026-10-13T14:50:35+00:00 +lastmod: 2026-10-20T14:50:35+00:00 draft: false tags: ["Chainguard Workspaces", "Security", "Configuration"] images: [] @@ -29,12 +29,13 @@ When a request reaches one of these hostnames, `chainctl` on your laptop or Chai | ------ | ------------------------------- | | `laptop` | Your laptop. For `claude` and `gcp`, `chainctl` sends the credential to the session's host, outside the VM, when you attach. For `github` and `cgr.dev`, `chainctl` answers each request from your laptop, so the credential never leaves your machine. | | `org` | Your Chainguard organization, such as the Chainguard App's access to your GitHub repositories. | +| `owner` | A login of yours that Chainguard holds. Only the `claude` service uses this source, after you run `chainctl develop claude login`, and only with the Anthropic API. Chainguard sends the session's host short-lived access tokens from the login, whether or not you're attached. Refer to [Let Chainguard hold your Claude login](/chainguard/workspaces/coding-agents/#let-chainguard-hold-your-claude-login). | | `seat` | Your Chainguard identity, which your laptop delegates to the session when you attach. Only the `chainguard` service uses this source. | | `off` | Nothing. The session can't use the service. | -A credential that `chainctl` sends to the session's host stays there until the session parks or the credential expires, so it keeps working after you close your terminal. Refer to [Use Claude Code in a session](/chainguard/workspaces/coding-agents/) for how long Claude's credential lasts, and to [Use your Google Cloud credentials in a session](#use-your-google-cloud-credentials-in-a-session) for Google Cloud's. +A credential that `chainctl` sends to the session's host stays there until the session parks or the credential expires, so it keeps working after you close your terminal. With the `owner` source, Chainguard keeps the credential fresh and sends it again after the session resumes. Refer to [Use Claude Code in a session](/chainguard/workspaces/coding-agents/) for how long Claude's credential lasts, and to [Use your Google Cloud credentials in a session](#use-your-google-cloud-credentials-in-a-session) for Google Cloud's. -Requests that `chainctl` answers from your laptop work only while your laptop serves the session, which it does while you're attached. If your terminal served one of them while you were attached, it keeps serving after you detach and keep the session running, until you press `Ctrl+C`. If nothing serves a session, these requests fail with an error that says no laptop is attached. +Requests that `chainctl` answers from your laptop work only while your laptop serves the session, which it does while you're attached. If your terminal served one of them while you were attached, it keeps serving after you detach with **Detach — keep running 4h**, **Detach — keep running for…**, or a `--keep` duration, or from a session you're already keeping running, until you press `Ctrl+C`. If nothing serves a session, these requests fail with an error that says no laptop is attached. ## What a session can reach by default {#what-a-session-can-reach-by-default} @@ -42,7 +43,7 @@ A new session can reach the following services without asking you: | Service | Default source | What it covers | | ------- | -------------- | -------------- | -| `claude` | `laptop` | The credential Claude Code on your laptop uses, for the Claude API's messages and models endpoints. | +| `claude` | `laptop`, or `owner` after you run `chainctl develop claude login` | The credential Claude Code on your laptop uses, or your Claude login held by Chainguard, for the Claude API's messages and models endpoints. Refer to [Let Chainguard hold your Claude login](/chainguard/workspaces/coding-agents/#let-chainguard-hold-your-claude-login) for which sessions use `owner`. | | `github` | `org` | `git` fetch and push for the session's repository, and for the repositories of your checkout's other github.com remotes where the Chainguard App is installed. To use the others, add them as remotes in the session, as described in [Choose the session's repository](/chainguard/workspaces/manage-sessions/#choose-the-sessions-repository). | | `cgr.dev` | `org` | Pulls images and lists tags from `cgr.dev` as the Chainguard platform, not as you, so it can't pull or list your organization's private images. | | `chainguard` | `seat` | `chainctl` and the Chainguard Model Context Protocol (MCP) servers in the session act as you, limited to read, Chainguard Checks, and MCP capabilities in the session's organization, within the permissions you hold. Refer to [Your Chainguard identity in a session](#your-chainguard-identity-in-a-session). | @@ -102,9 +103,9 @@ chainctl develop app/quiet-harbor --with gcp --parent $ORGANIZATION While you're attached, you can also turn `gcp` on or off from the session menu: press `Ctrl+]`, choose **Credentials**, choose `gcp`, and then choose **Set the source**. The change can take up to 30 seconds to reach the session. If `chainctl` says that the session's guest `was booted without the wiring that lets it use your Google credentials`, or the **Credentials** screen has no `gcp`, the session was created before it could use your Google credentials, so it can't use them. Delete it and create a new one with `chainctl develop --new --with gcp`. -The session's VM holds only a placeholder credential. Each time you attach, `chainctl` sends your Google Cloud credential to Chainguard, which keeps it outside the VM, adds it to the session's requests to Google APIs, and discards it when the session parks. Usually, `chainctl` sends a short-lived access token and renews it while you're attached. If you attach to a session you're already keeping running, however little of that time is left, `chainctl` sends your refresh token instead, and access lasts until the session parks. A session created with `--keep always` always gets the refresh token. If your application default credentials have no refresh token, such as a service account's, `chainctl` sends an access token either way. `chainctl` tells you which one it sent. +The session's VM holds only a placeholder credential. Each time you attach, `chainctl` sends your Google Cloud credential to Chainguard, which keeps it outside the VM, adds it to the session's requests to Google APIs, and discards it when the session parks. Usually, `chainctl` sends your refresh token, and access lasts until the session parks. A session created with `--keep park`, or with `chainctl` 0.2.382 or earlier, gets your refresh token only if you attach while you're keeping it running, however little of that time is left, or attach with a `--keep` duration such as `--keep 8h`. Otherwise, it gets a short-lived access token, which `chainctl` renews while you're attached. If your application default credentials have no refresh token, such as a service account's, `chainctl` sends an access token either way. `chainctl` tells you which one it sent. -If you detach with one of the session menu's **Detach — keep running** options, whatever duration you choose, `chainctl` sends your refresh token before it detaches, so access lasts until the session parks. If you exit the shell instead, `chainctl` can't send the refresh token, and access ends within an hour. The message `chainctl` prints when you detach says which applies. +In a session that got an access token, if you detach with one of the session menu's **Detach — keep running** options, whatever duration you choose, `chainctl` sends your refresh token before it detaches, so access lasts until the session parks. If you exit the shell instead, `chainctl` can't send the refresh token, and access ends within an hour. The message `chainctl` prints when you detach says which applies. While the session has your credential, code in it can use your Google Cloud access, and anything it creates with that access, such as a service account key, outlives the session. If the session's environment has an `egress` list, include `sts.googleapis.com` and the Google APIs the session calls. @@ -136,7 +137,7 @@ To change a session's credentials, pass one or more of the following flags to `c | Flag | What it does | | ---- | ------------ | | `--revoke ` | Takes access back from the session and from your laptop's remembered approvals. `` is `claude`, `cgr.dev`, `chainguard`, `github:/`, or `github:/+push`, which takes back only the push. | -| `--source =` | Changes where a credential comes from. `` is `laptop`, `org`, or `off`. The `claude` and `gcp` services take only `laptop` or `off`, and `chainguard` takes only `off`. To turn `chainguard` back on, use `--with chainguard`. | +| `--source =` | Changes where a credential comes from. `` is `laptop`, `org`, `owner`, or `off`. The `claude` service takes `laptop`, `owner`, or `off`, and takes `owner` only after you run `chainctl develop claude login` and only on a session that uses the Anthropic API. The `gcp` service takes only `laptop` or `off`, and `chainguard` takes only `off`. To turn `chainguard` back on, use `--with chainguard`. | | `--forget` | Removes everything your laptop remembers for the session's repository, without changing the session. | Changes to `github` have no effect on a session that acts on GitHub as you, as described in [Controls that don't apply to a session that acts as you](/chainguard/workspaces/github-as-you/#controls-that-dont-apply-to-a-session-that-acts-as-you). @@ -159,7 +160,7 @@ While you're attached, you can change a session's credentials without leaving it | ------ | ------------ | | **Allow more…** | Adds access. It takes the same entries as `--with`, such as `github:/+push` or `cgr.dev`. | | **Revoke…** | Takes access back from the session and from your laptop's remembered approvals, as `chainctl develop creds --revoke` does. For `github`, you choose a repository, or only its push. | -| **Set the source** | Changes where the credential comes from. For `claude` and `gcp`, you choose your laptop or no credential. For `github` and `cgr.dev`, you choose your laptop, your organization, or no credential. For `chainguard`, you choose your delegated Chainguard identity, which you then approve with `y`, or no credential. | +| **Set the source** | Changes where the credential comes from. For `claude` on the Anthropic API, you choose your laptop, your login held by Chainguard, or no credential. For `claude` on Vertex AI and for `gcp`, you choose your laptop or no credential. For `github` and `cgr.dev`, you choose your laptop, your organization, or no credential. For `chainguard`, you choose your delegated Chainguard identity, which you then approve with `y`, or no credential. | | **Widen…** | Asks for more capabilities or groups for `chainguard`. Type them as `CAP[,CAP...] [in GROUP[,GROUP...]]`, and then press `y` to approve the wider scope, or `d` to approve only the default scope. | The `claude` screen also offers **Use Vertex AI…** or **Use Anthropic…**, as described in [Switch a session to another provider](/chainguard/workspaces/coding-agents/#switch-a-session-to-another-provider). For a session that acts on GitHub as you, the `github` screen shows your GitHub account and offers no actions. If the list has no `gcp`, the session can't use your Google Cloud credentials, as described in [Use your Google Cloud credentials in a session](#use-your-google-cloud-credentials-in-a-session). diff --git a/content/chainguard/workspaces/getting-started.md b/content/chainguard/workspaces/getting-started.md index 3b0ad004fa..185b40186a 100644 --- a/content/chainguard/workspaces/getting-started.md +++ b/content/chainguard/workspaces/getting-started.md @@ -24,7 +24,7 @@ This guide walks you through signing up for Chainguard Workspaces, opening a ses -Sign up as described in [Set up Chainguard Checks and Chainguard Workspaces](/get-started/checks-and-workspaces/set-up/). You install or update `chainctl`, install the Chainguard App on the account that owns your repository, and run `chainctl develop init`, which turns on Chainguard Workspaces and Chainguard Checks together. You also need a local clone of a repository on github.com that you can push to. Optionally, install and log in to [Claude Code](https://code.claude.com/docs/en/overview) on your laptop, so you can use it in the session. +Sign up as described in [Set up Chainguard Checks and Chainguard Workspaces](/get-started/checks-and-workspaces/set-up/). You install or update `chainctl`, install the Chainguard App on the account that owns your repository, and run `chainctl develop init`, which turns on Chainguard Workspaces and Chainguard Checks together. You also need a local clone of a repository on github.com that you can push to. Optionally, install and log in to [Claude Code](https://code.claude.com/docs/en/overview) on your laptop, so you can use it in the session. Alternatively, run `chainctl develop claude login` to let Chainguard hold a Claude login for your sessions, so that Claude Code keeps working while you're detached, as described in [Let Chainguard hold your Claude login](/chainguard/workspaces/coding-agents/#let-chainguard-hold-your-claude-login). ## Step 2: Open a session @@ -54,7 +54,7 @@ The `git status` output matches your laptop's checkout at the moment you opened From here, you can work as you would on your laptop. For example: -- Run `claude` to start Claude Code. It uses your laptop's Claude Code login. Refer to [Use Claude Code in a session](/chainguard/workspaces/coding-agents/). +- Run `claude` to start Claude Code. It uses your laptop's Claude Code login, or the Claude login Chainguard holds for you if you ran `chainctl develop claude login`. Refer to [Use Claude Code in a session](/chainguard/workspaces/coding-agents/). - Run `run-ci` to run your repository's checks against the working tree, if your `.chainguard/ci.yaml` defines checks. - Commit and run `git push`. Your laptop's git `user.name` and `user.email` are already set in the session, and the Chainguard App, or Chainguard Develop if you connected your GitHub account, adds the credential for the push. @@ -62,7 +62,7 @@ Commits you make in a session aren't signed, because the session gets your git ` ## Step 4: Detach and return to the session -To detach, press `Ctrl+]` to open the session menu, then press `Enter` or `d` to choose **Detach — let it park**. Your terminal returns to your laptop's shell. The session keeps running for about 10 minutes, then parks to a snapshot and stops using compute. +To detach, press `Ctrl+]` to open the session menu, then press `Enter` or `d` to choose **Detach — keep running while busy**. Your terminal returns to your laptop's shell. The session keeps running while it's busy, such as during a build or a Claude Code turn. After it's been idle for 10 minutes, and no later than 24 hours after you last detach, it parks to a snapshot and stops using compute. To return, run `chainctl develop` again from the same directory: diff --git a/content/chainguard/workspaces/manage-sessions.md b/content/chainguard/workspaces/manage-sessions.md index 7da4b404af..b9a4de6d25 100644 --- a/content/chainguard/workspaces/manage-sessions.md +++ b/content/chainguard/workspaces/manage-sessions.md @@ -4,7 +4,7 @@ linktitle: "Manage sessions" description: "Open, detach from, return to, list, rename, and delete Chainguard Workspaces sessions, run several terminals in one, and keep a session running while you're away." type: "article" date: 2026-10-08T00:00:00+00:00 -lastmod: 2026-10-13T14:50:35+00:00 +lastmod: 2026-10-20T14:50:35+00:00 draft: false tags: ["Chainguard Workspaces", "chainctl", "Procedural"] images: [] @@ -62,8 +62,8 @@ While you're attached to a session, press `Ctrl+]` to open the session menu. You | Option | Key | What it does | | ------ | --- | ------------ | -| **Detach — let it park** | `d` or `Enter` | Returns you to your laptop's shell. The session keeps running for about 10 minutes, then parks. | -| **Detach — keep running 4h** | | Returns you to your laptop's shell and keeps the session running for 4 hours. | +| **Detach — keep running while busy** | `d` or `Enter` | Returns you to your laptop's shell. The session keeps running while it's busy and parks after it's been idle for 10 minutes, as described in [Keep a session running while you're away](#keep-a-session-running-while-youre-away). The option's hint shows the latest time it can keep running, such as `parks after 10m quiet, at most until 17:30`. | +| **Detach — keep running 4h** | | Returns you to your laptop's shell and keeps the session running for 4 hours, busy or not. | | **Detach — keep running for…** | | Asks for a duration, such as `90m`, or a time, such as `17:30`, up to 24 hours from now. | | **Park now** | | Returns you to your laptop's shell and parks the session right away, even one you're keeping running. To resume it, run `chainctl develop`, which waits for the park to finish. | | **Restart the host** | | Parks the session and resumes it on a new host while you stay attached. Running processes continue unless the snapshot can't be restored. | @@ -76,11 +76,11 @@ While you're attached to a session, press `Ctrl+]` to open the session menu. You The menu ignores what you type for a moment after it opens, so pause before you press a key. -The first option is what `d` or `Enter` does, and the detach options depend on the session. For a session you're already keeping running, the first option is **Detach — keeps running until** followed by a time. A session created with `--keep always` has one detach option, which shows how long it keeps running. The `--keep` flag also changes the first option, as described in [Keep a session running while you're away](#keep-a-session-running-while-youre-away). +The first option is what `d` or `Enter` does, and the detach options depend on the session. For a session you're already keeping running, the first option is **Detach — keeps running until** followed by a time, with `then while busy` after it when the session can keep running while it's busy after that time. A session created with `--keep always` has one detach option, which shows how long it keeps running. A session created with `--keep park`, or with `chainctl` 0.2.382 or earlier, has **Detach — let it park** instead of **Detach — keep running while busy**, and parks about 10 minutes after you detach, busy or not. The `--keep` flag also changes the first option, as described in [Keep a session running while you're away](#keep-a-session-running-while-youre-away). To send `Ctrl+]` to a program in the session, press it twice. To see every key, choose **Help**, or type `~?` wherever `~.` works. -If you exit the session's shell, for example with `exit`, any other terminals you opened in the session close too. If the session isn't already being kept running, `chainctl` asks whether to keep it running while you're away. Press `Esc` to let it park. +If you exit the session's shell, for example with `exit`, any other terminals you opened in the session close too. If the session isn't already being kept running, `chainctl` asks whether to keep it running while you're away. Press `Esc` to keep it running only while it's busy, as **Detach — keep running while busy** does. In a session that has **Detach — let it park** instead, `Esc` lets it park. ## Return to a session {#return-to-a-session} @@ -100,7 +100,16 @@ Only one `chainctl` can be attached to a session at a time. If you attach from a A session that keeps running uses compute while you're away, but an agent in it can keep working. It counts against your organization's monthly allowance the whole time it runs, as described in [Availability and limits](/chainguard/workspaces/overview/#availability-and-limits). -To keep a session running, choose one of the **Detach — keep running** options in the session menu. +When you detach, a session keeps running while it's busy, and parks after it's been idle for 10 minutes. A session is busy while any of the following is true: + +- Its CPU use averages more than a tenth of a vCPU over 5 minutes, or its network traffic, sent and received together, exceeds 256 KiB in that time. +- Claude Code in the session is working on a turn. +- A `run-ci` run that started in the session is running, as described in [Run checks in a Workspaces session](/chainguard/checks/run-checks/#run-checks-in-a-workspaces-session). +- The `busy` command holds the session, as described in [Mark a session busy](#mark-a-session-busy). + +Claude Code that waits at a permission prompt or for your input isn't busy, so a session can park while an agent waits for you. Even while it's busy, a session parks no later than 24 hours after you last detach. A `chainctl develop check` from your laptop counts as attaching. While your organization's monthly compute allowance is used up, being busy doesn't keep a detached session running. + +To keep a session running whether or not it's busy, choose **Detach — keep running 4h** or **Detach — keep running for…** in the session menu. The session keeps running until the time you choose, and then, unless you created it with `--keep park` or `chainctl` 0.2.382 or earlier, while it's busy. To decide ahead of time that a session keeps running when you detach, pass `--keep` with a duration of up to 24 hours when you open or return to it: @@ -110,7 +119,7 @@ chainctl develop --keep 8h --parent $ORGANIZATION With `--keep 8h`, the menu's first option becomes **Detach — keep running 8h**, and exiting the shell keeps the session running without asking. -For a long-running task, create a new session with `--keep always`. That session keeps running instead of parking when you detach, until 7 days after you last detach from it: +For a long-running task, create a new session with `--keep always`. That session keeps running instead of parking when you detach, busy or not, until 7 days after you last detach from it: ```shell chainctl develop --keep always --name migration --parent $ORGANIZATION @@ -118,9 +127,33 @@ chainctl develop --keep always --name migration --parent $ORGANIZATION Because it doesn't park, a `--keep always` session can use up the monthly allowance in a few days. To stop it sooner, choose **Park now** in the session menu, or delete the session. -Claude Code can keep working after you close the terminal, for as long as its credential lasts. Refer to [Keep Claude Code working while you're away](/chainguard/workspaces/coding-agents/#keep-claude-code-working-while-youre-away). +To create a new session that parks about 10 minutes after you detach, busy or not, pass `--keep park`: + +```shell +chainctl develop --keep park --parent $ORGANIZATION +``` + +Claude Code can keep working after you close the terminal. With a Claude login that Chainguard holds for you, it keeps working for as long as the session runs. Refer to [Keep Claude Code working while you're away](/chainguard/workspaces/coding-agents/#keep-claude-code-working-while-youre-away). + +If you detach with **Detach — keep running 4h**, **Detach — keep running for…**, or a `--keep` duration, or from a session you're already keeping running, the terminal you detached from keeps serving the credentials that come from your laptop, such as a `cgr.dev` login you switched to your laptop, until you press `Ctrl+C` or close the terminal. Once nothing serves the session, requests that need your laptop fail until you return to it. Refer to [How credentials reach a session](/chainguard/workspaces/credentials/#how-credentials-reach-a-session). + +### Mark a session busy {#mark-a-session-busy} + +Work that waits without using the CPU or network, such as a script that waits on a remote job, doesn't make a session busy. To keep a detached session running while such work runs, use the `busy` command, which every session has at `/usr/local/bin/busy`: + +| Command | What it does | +| ------- | ------------ | +| `busy -- CMD [ARG...]` | Runs `CMD` and keeps the session busy until it exits. `busy` exits with `CMD`'s exit status. | +| `busy --for DURATION [LABEL]` | Keeps the session busy for a duration, such as `90s`, `30m`, `2h`, or `1d`. | +| `busy --clear [LABEL]` | Ends the `busy --for` hold with that label. | + +A label names a hold, so you can end one without the others. It has 1 to 32 lowercase letters, digits, and hyphens, and defaults to `busy`. For example, the following command keeps the session running until a release build finishes: + +```shell +busy -- make release +``` -For a credential that your laptop serves, such as a `cgr.dev` login you switched to your laptop, the terminal you detached from keeps serving the session until you press `Ctrl+C` or close the terminal. After that, requests that need your laptop fail until you return to the session. Refer to [How credentials reach a session](/chainguard/workspaces/credentials/#how-credentials-reach-a-session). +Whatever `busy` holds, a session parks no later than 24 hours after you last detach. ## Use several terminals in a session {#use-several-terminals-in-a-session} @@ -155,7 +188,7 @@ chainctl develop --new --name scratch --parent $ORGANIZATION This command creates a session named `app/scratch`. Without `--name`, `chainctl` generates a name. Once a directory has several sessions, return to one by its name or short ID. -The `--name`, `--env`, `--check`, `--cache`, and `--keep always` flags each open a new session, so you don't need `--new` with them. +The `--name`, `--env`, `--check`, `--cache`, `--keep always`, and `--keep park` flags each open a new session, so you don't need `--new` with them. ## List sessions {#list-sessions} @@ -170,11 +203,11 @@ The output shows each session's name, the branch checked out in it, its state, a ``` NAME | BRANCH | STATE | LAST USED -----------------------|-----------|------------------------|----------- - acme/app/quiet-harbor | main | running, parks in 6m | 4m ago + acme/app/quiet-harbor | main | idle (parks in 6m) | 4m ago acme/app/scratch | fix-tests | parked, expires Oct 13 | 2d ago ``` -The `STATE` column tells you whether a session is running, when it parks or stops running, and when a parked session expires. To add each session's commit, environment, and directory, pass `-o wide`. To include expired sessions, pass `--expired`. +The `STATE` column tells you whether a session is running, when it parks or stops running, and when a parked session expires. For a detached session, it also says whether the session is busy, such as `running (busy: agent turn, as of 13:40; at most until Oct 21 13:35)`, or how long a hold you placed lasts, such as `running, until 17:30, then while busy`. A session shown as `idle`, such as `idle (parks in 6m)`, is running but not busy, and the column shows when it parks. To add each session's commit, environment, and directory, pass `-o wide`. To include expired sessions, pass `--expired`. To list every user's sessions in the organization, with an `OWNER` column, pass `--all`. Only organization owners can use `--all`, and you can return to, rename, or delete only your own sessions. diff --git a/content/chainguard/workspaces/overview.md b/content/chainguard/workspaces/overview.md index 7d1c7fd28a..18eb11b1e4 100644 --- a/content/chainguard/workspaces/overview.md +++ b/content/chainguard/workspaces/overview.md @@ -4,7 +4,7 @@ linktitle: "Overview" description: "Learn how Chainguard Workspaces runs your repository and your coding agents in a remote microVM session without putting your credentials in the session." type: "article" date: 2026-10-08T00:00:00+00:00 -lastmod: 2026-10-15T12:09:53+00:00 +lastmod: 2026-10-20T12:09:53+00:00 draft: false tags: ["Chainguard Workspaces", "Overview", "AI"] images: [] @@ -35,7 +35,7 @@ The session's packages come from Chainguard OS. If your repository has a `.chain Sessions keep running after you detach, then park: -- When you detach, the session keeps running for about 10 minutes. You can also ask it to keep running for longer, up to 24 hours at a time. +- When you detach, the session keeps running while it's busy, such as during a build or a Claude Code turn, and until it's been idle for 10 minutes, up to 24 hours after you last detach. You can also keep it running for a time you choose, up to 24 hours, or create it with `--keep always`. - After that, the session *parks*: Chainguard saves its memory and disk to a snapshot and stops the VM, so it uses no compute. - When you return, the session resumes from the snapshot in seconds, with your processes, files, and shell as you left them. - A parked session expires 5 days after it parks. @@ -44,18 +44,18 @@ Each session is its own VM. You can open several sessions on the same repository ## How sessions get credentials -No long-lived credential enters a session. Instead, the session reaches each service through a local hostname, such as `http://github/` or `http://claude/`. Outside the VM, Chainguard or `chainctl` on your laptop adds the credential to each request. Depending on the service, the credential comes from your laptop, such as your Claude Code login, or from your Chainguard organization, such as the Chainguard App's access to your repositories. +No long-lived credential enters a session. Instead, the session reaches each service through a local hostname, such as `http://github/` or `http://claude/`. Outside the VM, Chainguard or `chainctl` on your laptop adds the credential to each request. Depending on the service, the credential comes from one of three places: your laptop (such as your Claude Code login), your Chainguard organization (such as the Chainguard App's access to your repositories), or a login that Chainguard holds for you (such as your Claude login after you run `chainctl develop claude login`). By default, a session can reach the following: -- Claude, with the same credential Claude Code uses on your laptop. +- Claude, with the same credential Claude Code uses on your laptop, or with your Claude login held by Chainguard. - The session's own GitHub repository, for fetch and push, and the other github.com repositories that your checkout's remotes point to, where the Chainguard App is installed. To use those, add them as remotes in the session. - `cgr.dev`, as the Chainguard platform rather than as you. - Your Chainguard identity, limited to the read, Chainguard Checks, and Model Context Protocol (MCP) capabilities you hold in the session's organization, while you're attached and for up to an hour after you detach. When the session asks for anything else, such as fetching another private repository, `chainctl` asks you on your terminal. You can approve requests ahead of time, or take access back, at any point. Refer to [Manage session credentials](/chainguard/workspaces/credentials/) for details. -Claude Code can keep working after you close your terminal, for as long as its credential lasts, as described in [Keep Claude Code working while you're away](/chainguard/workspaces/coding-agents/#keep-claude-code-working-while-youre-away). A service that you set to use a credential from your laptop, such as `github` or `cgr.dev`, works only while you're attached or while the terminal you detached from keeps serving it. +Claude Code can keep working after you close your terminal, for as long as its credential lasts. With your Claude login held by Chainguard, it works whether or not you're attached, for as long as the session runs, as described in [Keep Claude Code working while you're away](/chainguard/workspaces/coding-agents/#keep-claude-code-working-while-youre-away). A service that you set to use a credential from your laptop, such as `github` or `cgr.dev`, works only while you're attached or while the terminal you detached from keeps serving it. ## Network access @@ -82,9 +82,9 @@ During the beta, Chainguard Workspaces has the following limits: - A session can't forward ports to your laptop. - `chainctl develop init` turns on a free monthly allowance, which resets on the first day of each month (UTC) and includes 500 vCPU-hours of Workspaces. Chainguard Checks has its own allowance. Each user can have one session at a time, including a parked one, and the organization can have three. An allowance arranged with your Chainguard account team can differ. -A session counts its vCPUs against the allowance for every hour its VM runs, whether it's busy or idle. A session with the default 4 vCPUs uses 4 vCPU-hours an hour, including the roughly 10 minutes it keeps running after you detach, and a parked session uses none. A 4-vCPU session created with `--keep always` and left running uses the month's allowance in about 5 days. Chainguard doesn't show your usage during the beta. +A session counts its vCPUs against the allowance for every hour its VM runs, whether it's busy or idle. A session with the default 4 vCPUs uses 4 vCPU-hours an hour, including the time it keeps running while it's busy after you detach and the 10 idle minutes before it parks, and a parked session uses none. A 4-vCPU session created with `--keep always` and left running uses the month's allowance in about 5 days. Chainguard doesn't show your usage during the beta. -When the allowance is used up, you can't create a session or resume a parked one until the allowance resets, but sessions that are already running aren't stopped. Refer to [Your organization's monthly compute allowance is used up](/chainguard/workspaces/troubleshooting/#your-organizations-monthly-compute-allowance-is-used-up) for details. +When the allowance is used up, you can't create a session or resume a parked one until the allowance resets, and being busy no longer keeps a detached session running, so it parks about 10 minutes after you detach. Sessions you're attached to keep running until you detach. Refer to [Your organization's monthly compute allowance is used up](/chainguard/workspaces/troubleshooting/#your-organizations-monthly-compute-allowance-is-used-up) for details. ## Get help diff --git a/content/chainguard/workspaces/session-environment.md b/content/chainguard/workspaces/session-environment.md index ac0bbf4727..3edc7749ce 100644 --- a/content/chainguard/workspaces/session-environment.md +++ b/content/chainguard/workspaces/session-environment.md @@ -4,7 +4,7 @@ linktitle: "Session environment" description: "Choose the packages, tools, and network access a Chainguard Workspaces session gets, from your repository's .chainguard/develop.yaml or .chainguard/ci.yaml file, a file of your own, or the default environment." type: "article" date: 2026-10-08T00:00:00+00:00 -lastmod: 2026-10-15T12:09:53+00:00 +lastmod: 2026-10-20T12:09:53+00:00 draft: false tags: ["Chainguard Workspaces", "Configuration", "Reference"] images: [] @@ -33,7 +33,7 @@ The order is the same for a session opened from a local directory and one opened If your repository has neither a `.chainguard/develop.yaml` nor a `.chainguard/ci.yaml` file and you don't pass `--env`, `chainctl` opens the session on the default environment and tells you so. When you run `chainctl develop` with `--non-interactive`, it refuses instead, so pass `--env default` explicitly in scripts. -Whatever its environment, every session also gets `git`, `gh`, `chainctl`, `curl`, `bash`, `bash-completion`, `busybox`, and `gnutar`. Nothing else is installed unless the environment lists it, including Claude Code (`claude`). By default, the session's shell and each terminal you open from the session menu run `bash`, with completion and a history file at `~/.bash_history`. `bash` reads `~/.bashrc` last, if you create one in the session, so your own settings take precedence. +Whatever its environment, every session also gets `git`, `gh`, `chainctl`, `curl`, `bash`, `bash-completion`, `busybox`, and `gnutar`. Every session also has the `busy` command at `/usr/local/bin/busy`, which keeps a detached session running while it holds the session, as described in [Mark a session busy](/chainguard/workspaces/manage-sessions/#mark-a-session-busy). Nothing else is installed unless the environment lists it, including Claude Code (`claude`). By default, the session's shell and each terminal you open from the session menu run `bash`, with completion and a history file at `~/.bash_history`. `bash` reads `~/.bashrc` last, if you create one in the session, so your own settings take precedence. `chainctl` never writes to your directory. To find out which environment a session uses, read `/etc/chainguard/session.yaml` in the session. To see each session's environment from your laptop, run `chainctl develop list -o wide`. diff --git a/content/chainguard/workspaces/troubleshooting.md b/content/chainguard/workspaces/troubleshooting.md index 2fd766878b..ddff8edb6c 100644 --- a/content/chainguard/workspaces/troubleshooting.md +++ b/content/chainguard/workspaces/troubleshooting.md @@ -4,7 +4,7 @@ linktitle: "Troubleshooting" description: "Fix common problems with Chainguard Workspaces, including sign-up failures, permission errors, sessions that won't open, Claude Code errors, failed pushes, and usage limits." type: "article" date: 2026-10-08T00:00:00+00:00 -lastmod: 2026-10-15T12:09:53+00:00 +lastmod: 2026-10-20T12:09:53+00:00 draft: false tags: ["Chainguard Workspaces", "Troubleshooting"] images: [] @@ -125,17 +125,17 @@ The following sections describe the most common causes. ### No credential has arrived {#no-credential-has-arrived} -If the error says that `none has arrived`, the session has no Claude credential. Claude Code might show only a `503` error. Update `chainctl` to the [minimum version](/get-started/checks-and-workspaces/set-up/#install-or-update-chainctl) or later, run `claude` on your laptop and log in, and then attach to the session with `chainctl develop`. If you use Claude through Vertex AI, run `gcloud auth application-default login` on your laptop instead of logging in to Claude. +If the error says that `none has arrived`, the session has no Claude credential. Claude Code might show only a `503` error. Update `chainctl` to the [minimum version](/get-started/checks-and-workspaces/set-up/#install-or-update-chainctl) or later, log in to Claude with `chainctl develop claude login` or with `claude` on your laptop, and then attach to the session with `chainctl develop`. If you use Claude through Vertex AI, run `gcloud auth application-default login` on your laptop instead of logging in to Claude. ### The session's host is too old {#the-sessions-host-is-too-old} -If the error says that the session's host `predates laptop credential push`, or `chainctl` says that the session's host was started before it could send model credentials, the host can't take a credential. Attach to the session with a current `chainctl`, press `Ctrl+]`, and choose **Restart the host**. You can also detach, let the session park, and attach again. +If the error says that the session's host `predates laptop credential push`, or `chainctl` says that the session's host was started before it could send model credentials, the host can't take a credential. Attach to the session with a current `chainctl`, press `Ctrl+]`, and choose **Restart the host**. You can also choose **Park now** in the session menu, and then attach again. ### The credential sent to the session expired {#the-credential-sent-to-the-session-expired} -If the error says that `the owner's Claude login token sent to this session expired`, the short-lived access token from your stored Claude login ran out. `chainctl` renews it while you're attached, and while a terminal that you detached from with a **Detach — keep running** option stays open. Attach again to send a fresh one. +If the error says that `the owner's Claude login token sent to this session expired`, the short-lived access token from your stored Claude login ran out. `chainctl` renews it while you're attached. It also renews it while the terminal you detached from stays open, if you detached with **Detach — keep running 4h**, **Detach — keep running for…**, or a `--keep` duration, or from a session you're already keeping running. Attach again to send a fresh one. -To keep a long unattended task from stopping, use a token from `claude setup-token`, as described in [Keep Claude Code working while you're away](/chainguard/workspaces/coding-agents/#keep-claude-code-working-while-youre-away). +To keep a long unattended task from stopping, run `chainctl develop claude login`, as described in [Let Chainguard hold your Claude login](/chainguard/workspaces/coding-agents/#let-chainguard-hold-your-claude-login). If you use Claude through Vertex AI, the error says instead that your Google credential or access token sent to the session for Vertex AI no longer works or expired. Attach again to send a fresh one. @@ -157,7 +157,25 @@ If `chainctl` says that `your Claude login on this laptop` expires soon or has e ### You aren't logged in to Claude {#you-arent-logged-in-to-claude} -If `chainctl` says `claude: nothing to send` when you attach, it found no Claude login or Google credentials on your laptop. Run `claude` on your laptop and log in, or run `gcloud auth application-default login` if you use Claude through Vertex AI. `chainctl` tries again while you're attached. +If `chainctl` says `claude: nothing to send` when you attach, it found no Claude login or Google credentials on your laptop. Run `claude` on your laptop and log in, or run `gcloud auth application-default login` if you use Claude through Vertex AI. `chainctl` tries again while you're attached. With the Anthropic API, you can also run `chainctl develop claude login`, and then attach again. + +### Your Claude login held by Chainguard doesn't work {#your-claude-login-held-by-chainguard-doesnt-work} + +If Claude Code in the session reports that `claude in this session uses its owner's Claude login held by Chainguard, and none is usable now`, or `chainctl` says when you attach that `your Claude login held by Chainguard no longer works`, the login that Chainguard held for you ended, or you ran `chainctl develop claude logout`. Run `chainctl develop claude login`, and then attach to the session again. + +To use your laptop's credential in the session instead, switch its source to `laptop`. Replace `$SESSION` with the session's short ID, which the error includes: + +```shell +chainctl develop creds $SESSION --source claude=laptop +``` + +### chainctl develop claude login fails {#chainctl-develop-claude-login-fails} + +If `chainctl develop claude login` fails, find its message in the following list: + +- `the pasted code is not the code#state Anthropic's page shows`, or `the pasted code is from another login`: you pasted something other than the code that the page from this login shows. Run `chainctl develop claude login` again, and paste the whole code that the new page shows. +- `the Claude login was not finished in time`: the login must finish within 5 minutes. Run the command again. +- `Anthropic refused the authorization code (expired or already used)`: run `chainctl develop claude login` again, and paste the new code right away. ### Claude Code isn't installed in the session {#claude-code-isnt-installed-in-the-session} @@ -226,6 +244,15 @@ On your laptop, `chainctl develop github status` shows which accounts the checko The `/tmp` directory in a session is held in memory and limited to a quarter of the session's memory, which is 4 GB with the default 16 GB. Writing large files there uses memory that your processes need. Put large files under `/var/tmp` or `/work`, which are on the session's disk, 50 GB by default. To change a session's memory or disk, refer to [Resources](/chainguard/workspaces/session-environment/#resources). +## A session parked while an agent was working {#a-session-parked-while-an-agent-was-working} + +When you return to a parked session, `chainctl` says why it parked. A session that keeps running while it's busy parks for one of the following reasons: + +- `parked after 10m quiet; last busy 13:40 UTC (agent-turn)`, or `parked after 10m detached`: the session wasn't busy for 10 minutes. Claude Code that waits at a permission prompt or for your input isn't busy. To keep a session running while an agent waits, choose **Detach — keep running 4h** or **Detach — keep running for…** when you detach, or let the agent work without asking, as described in [Choose a permission mode](/chainguard/workspaces/coding-agents/#choose-a-permission-mode). +- `parked: 24h since you last attached; the guest still reported busy`: the session reached its limit of 24 hours after you last detached. For a task that runs longer, create a session with `--keep always`. + +While your organization's monthly compute allowance is used up, being busy doesn't keep a session running, as described in [Your organization's monthly compute allowance is used up](#your-organizations-monthly-compute-allowance-is-used-up). For what counts as busy, refer to [Keep a session running while you're away](/chainguard/workspaces/manage-sessions/#keep-a-session-running-while-youre-away). + ## A session started fresh instead of resuming {#a-session-started-fresh-instead-of-resuming} Rarely, Chainguard can't restore a parked session's snapshot. The session then starts fresh, and `chainctl` says that the parked snapshot couldn't be restored and that uncommitted work was lost. Push your work regularly so that a lost snapshot doesn't cost you much. @@ -236,7 +263,7 @@ A parked session expires 5 days after it parks, and an expired session can't be ## Your organization's monthly compute allowance is used up {#your-organizations-monthly-compute-allowance-is-used-up} -If `chainctl develop` fails with a `FailedPrecondition` error that says `this month's compute allowance is used up`, your organization has used its monthly vCPU-hours of Workspaces. Until the allowance resets on the first day of the month (UTC), you can't create a session or resume a parked one, and a session created with `--keep always` parks after you detach instead of staying up. Sessions that are already running aren't stopped. +If `chainctl develop` fails with a `FailedPrecondition` error that says `this month's compute allowance is used up`, your organization has used its monthly vCPU-hours of Workspaces. Until the allowance resets on the first day of the month (UTC), you can't create a session or resume a parked one. Being busy no longer keeps a detached session running, so it parks about 10 minutes after you detach, and a session created with `--keep always` parks after you detach instead of staying up. Sessions you're attached to keep running until you detach. A parked session still expires 5 days after it parks, even if the allowance hasn't reset yet, so push your work regularly. To learn how sessions use the allowance, refer to [Availability and limits](/chainguard/workspaces/overview/#availability-and-limits). To continue before the allowance resets, [contact Chainguard](https://www.chainguard.dev/contact?utm=docs). diff --git a/content/get-started/checks-and-workspaces/how-it-works.md b/content/get-started/checks-and-workspaces/how-it-works.md index 094c466a47..efa19362da 100644 --- a/content/get-started/checks-and-workspaces/how-it-works.md +++ b/content/get-started/checks-and-workspaces/how-it-works.md @@ -1,7 +1,7 @@ --- title: "How Chainguard Checks and Chainguard Workspaces isolate your code" date: 2026-10-15T12:09:53+00:00 -lastmod: 2026-10-16T11:36:21+00:00 +lastmod: 2026-10-20T11:36:21+00:00 linktitle: "How it works" description: "The security model of Chainguard Checks and Chainguard Workspaces in one place: microVM isolation, credentials kept outside the VM, network allowlists, trust rings, and the run and session lifecycles." type: "article" @@ -45,7 +45,7 @@ Neither product puts a long-lived credential in the VM. Where a check or session | | Chainguard Checks | Chainguard Workspaces | | -- | -- | -- | | How code authenticates | A check can request a [workload identity](/chainguard/checks/identity-and-trust/). Chainguard Checks issues the check an OpenID Connect (OIDC) token that lasts five minutes, and renews it while the check runs. | The session reaches each service through a local hostname, such as `http://github/` or `http://claude/`. `chainctl` on your laptop, or Chainguard, adds the credential to each request. | -| What the VM holds | For Google Cloud, a credential configuration and sealed stand-in tokens. Chainguard Checks swaps in the real tokens only on requests to `sts.googleapis.com` and other `googleapis.com` subdomains. For Chainguard, nothing. | A placeholder at most. For `github` and `cgr.dev` from your laptop, the credential never leaves your machine. For `claude` and `gcp`, `chainctl` sends it to the session's host, outside the VM, and the host discards it when the session parks. | +| What the VM holds | For Google Cloud, a credential configuration and sealed stand-in tokens. Chainguard Checks swaps in the real tokens only on requests to `sts.googleapis.com` and other `googleapis.com` subdomains. For Chainguard, nothing. | A placeholder at most. For `github` and `cgr.dev` from your laptop, the credential never leaves your machine. For `claude` and `gcp`, `chainctl` sends it to the session's host, outside the VM, and the host discards it when the session parks. For a session that uses a Claude login Chainguard holds for you, Chainguard sends the host short-lived access tokens from it instead, attached or not, and sends them again when the session resumes. | | Who decides | `identities.yaml` on the pull request's base branch, and the `trust` section on your default branch. | Your organization's policy and the session's credential settings. A request beyond the defaults needs your approval on your terminal. | Code in the VM can't read the real credentials, but it can use them. Each request it sends carries the credential's access, and anything it creates with that access, such as a Google Cloud service account key, outlives the check or session. Grant each workload identity only the access its checks need, and review a session's credentials before you let an agent work in it unattended. Refer to [Manage session credentials](/chainguard/workspaces/credentials/). @@ -131,9 +131,9 @@ A session moves through the following states: | State | What it means | What moves it on | | -- | -- | -- | | Creating | `chainctl develop` creates the VM, syncs your directory into `/work`, and installs the session's packages. | When it's ready, your terminal attaches. | -| Attached | Your terminal is connected to the session's shell. `chainctl` answers the requests that use your laptop's credentials, and sends your Claude and Google Cloud credentials to the session's host. | When you detach, the session keeps running. **Park now** in the session menu parks it right away. | -| Running, detached | The session keeps running, and an agent in it can keep working. It still uses compute. | After about 10 minutes, or after the time you chose with **Detach — keep running** or `--keep`, up to 24 hours, the session parks. A `--keep always` session parks 7 days after you last detach. Attaching again returns it to attached. | -| Parked | Chainguard saves the session's memory and disk to a snapshot and stops the VM, so it uses no compute. The host discards the credentials `chainctl` sent it. | Attaching resumes it from the snapshot in seconds, with processes, files, and shell as you left them. Five days after parking, it expires. | +| Attached | Your terminal is connected to the session's shell. `chainctl` answers the requests that use your laptop's credentials, and sends your Claude and Google Cloud credentials to the session's host. For a session that uses a Claude login Chainguard holds for you, `chainctl` sends nothing for Claude. | When you detach, the session keeps running. **Park now** in the session menu parks it right away. | +| Running, detached | The session keeps running, and an agent in it can keep working. It still uses compute. | The session keeps running while it's busy, such as during a build, a Claude Code turn, a `run-ci` run, or a `busy` command, and parks after it's been idle for 10 minutes, no later than 24 hours after you last detach. A time you chose with **Detach — keep running** or `--keep` keeps it running until then, and then while it's busy. A `--keep park` session parks about 10 minutes after you detach, busy or not, and a `--keep always` session parks 7 days after you last detach. Attaching again returns it to attached. | +| Parked | Chainguard saves the session's memory and disk to a snapshot and stops the VM, so it uses no compute. The host discards the credentials `chainctl` sent it. | Attaching resumes it from the snapshot in seconds, with processes, files, and shell as you left them. When the session resumes, Chainguard sends the host fresh access tokens from a Claude login it holds for you, without waiting for you to attach. Five days after parking, it expires. | | Expired | Chainguard discards the VM and the snapshot. The session can't be resumed, but it stays in `chainctl develop list --expired`, and its name stays in use. | `chainctl develop delete` removes it. | However a session is used, its VM runs for at most 6 days at a stretch. Then Chainguard parks the session and resumes it right away, the same way the session menu's **Restart the host** option does, so a session in long use isn't cut off. diff --git a/content/get-started/checks-and-workspaces/set-up.md b/content/get-started/checks-and-workspaces/set-up.md index f4d6224d61..7e6bb99ab5 100644 --- a/content/get-started/checks-and-workspaces/set-up.md +++ b/content/get-started/checks-and-workspaces/set-up.md @@ -46,7 +46,7 @@ Before you begin, make sure you have the following: You sign up with `chainctl`, and you use it with both products: `chainctl checks` for Chainguard Checks and `chainctl develop` for Chainguard Workspaces. If you don't have it yet, follow the [chainctl installation guide](/platform/chainctl-usage/how-to-install-chainctl/). -Chainguard Checks and Chainguard Workspaces need `chainctl` 0.2.382 or later. Earlier releases can't sign you up as this page describes or run Claude Code in a session. Both products change often during the beta, so if you already have `chainctl`, update it to the latest release: +Chainguard Checks and Chainguard Workspaces need `chainctl` 0.2.386 or later. Releases before 0.2.383 can't keep a detached session running while it's busy or use a Claude login that Chainguard holds, and releases before 0.2.382 can't sign you up as this page describes or run Claude Code in a session. Both products change often during the beta, so if you already have `chainctl`, update it to the latest release: ```shell sudo chainctl update @@ -54,6 +54,8 @@ sudo chainctl update If you installed `chainctl` with Homebrew, run `brew upgrade chainctl` instead. Refer to [Updating chainctl](/platform/chainctl-usage/how-to-install-chainctl/#updating-chainctl) for details. +Updating doesn't change the sessions you already have. A session created with `chainctl` 0.2.382 or earlier doesn't keep running while it's busy. Unless you keep it running, it parks about 10 minutes after you detach, as described in [Keep a session running while you're away](/chainguard/workspaces/manage-sessions/#keep-a-session-running-while-youre-away). + ## Install the Chainguard App {#install-the-chainguard-app} The Chainguard App is a GitHub App that connects your repositories to Chainguard. Chainguard Checks receives pull request events and reports results through it, and by default, Workspaces sessions fetch and push your repository through it. [Guardener](/chainguard/guardener/) uses the same app.