feat: share client state through --account #52

Merged
claudiomaradonna merged 3 commits from feat/account-state into master 2026-10-21 16:20:38 +02:00
Collaborator

Why

A launch kept its client state, logins included, in its identity's
folder, so one identity could hold only one login per client. Using a
personal and a company Claude subscription with the same SSH key, forge
token, and goals meant two identity folders with copied files.

What changed

  • --account NAME, or AZKABAN_ACCOUNT in an identity's env.<client>
    or env, puts the client's state in ~/.azkaban/accounts/NAME/<client>.
    The option wins over env.<client>, which wins over env; the
    workspace file still cannot set it. Without an account, the identity's
    own state serves as before.
  • An account is shared by every identity that names it; identities that
    must stay apart name different accounts.
  • An invalid name or a symlink on the account's state path stops the
    launch before the engine, creating nothing.
  • A launch with an account prints <client>: account: <name>: state <path>
    after the identity line.
  • The README gains an Accounts section; the help, adapter guide,
    headless contract, and example env follow.

Out of scope: a per-account API key (a key in the identity's env
reaches every account), moving existing state, and commands to list or
delete accounts.

How to verify

  • claude . --account work --dry-run prints the account line on
    standard error, mounts ~/.azkaban/accounts/work/claude/config, and
    creates nothing.
  • claude . --account ../x stops with invalid account name '../x'.
  • make test TESTS=account runs the new suite.

On the tip, make lint && .agents/hooks/shellcheck.sh repo && make test
exits 0, with 31 test files and 0 failures. make test-e2e, which needs
real Podman, was not run.

Considerations

Sharing an account across identities is deliberate: a hook or setting
one identity's session writes there runs in the sessions of every other
identity that names it, with that identity's credentials. Accounts and
Identities in the README say so. The symlink check on the client state
path now runs once the identity's files have loaded, so an unnamed
launch with a symlinked state path prints the workspace line before it
refuses.

## Why A launch kept its client state, logins included, in its identity's folder, so one identity could hold only one login per client. Using a personal and a company Claude subscription with the same SSH key, forge token, and goals meant two identity folders with copied files. ## What changed - `--account NAME`, or `AZKABAN_ACCOUNT` in an identity's `env.<client>` or `env`, puts the client's state in `~/.azkaban/accounts/NAME/<client>`. The option wins over `env.<client>`, which wins over `env`; the workspace file still cannot set it. Without an account, the identity's own state serves as before. - An account is shared by every identity that names it; identities that must stay apart name different accounts. - An invalid name or a symlink on the account's state path stops the launch before the engine, creating nothing. - A launch with an account prints `<client>: account: <name>: state <path>` after the identity line. - The README gains an Accounts section; the help, adapter guide, headless contract, and example env follow. Out of scope: a per-account API key (a key in the identity's `env` reaches every account), moving existing state, and commands to list or delete accounts. ## How to verify - `claude . --account work --dry-run` prints the account line on standard error, mounts `~/.azkaban/accounts/work/claude/config`, and creates nothing. - `claude . --account ../x` stops with `invalid account name '../x'`. - `make test TESTS=account` runs the new suite. On the tip, `make lint && .agents/hooks/shellcheck.sh repo && make test` exits 0, with 31 test files and 0 failures. `make test-e2e`, which needs real Podman, was not run. ## Considerations Sharing an account across identities is deliberate: a hook or setting one identity's session writes there runs in the sessions of every other identity that names it, with that identity's credentials. Accounts and Identities in the README say so. The symlink check on the client state path now runs once the identity's files have loaded, so an unnamed launch with a symlinked state path prints the workspace line before it refuses.
Merge the source's changes since efb8e11 as its UPGRADING.md
describes: a main-checkout guard wired into each client, a bubblewrap
sandbox for running a commit's code, the check-issue skill with its
verdict template, the review template in place of review-pr/review.md,
step rules moved from AGENTS.md into their skills, a remote choice
before a first push, and English for tracked project output.

The Claude settings deny Workflow, ScheduleWakeup, ReportFindings, and
ListAgents, as agreed. The source's evals/ stays in the source, as its
maintainer tooling, and AGENTS.md keeps no Members section.
A launch keeps its client state in its identity's folder, so one
identity could hold only one login per client. --account NAME, or
AZKABAN_ACCOUNT in the identity's env or env.<client>, puts the state
in ~/.azkaban/accounts/NAME/<client> instead, shared by every identity
that names it. A name follows the identity-name rule, a symlink on the
path stops the launch, and the launch reports the account it uses.
Without an account the identity's state serves as before.
The README explains how one identity works with several client logins
through --account or AZKABAN_ACCOUNT, where an account's state lives,
and that an account is shared, hooks and settings included, by every
identity that names it. The adapter guide, the headless contract, and
the identity env example follow.
claudiomaradonna deleted branch feat/account-state 2026-10-21 16:20:42 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
claudiomaradonna/azkaban!52
No description provided.