# Onboarding: solo PA

Ten minutes end to end. One command scaffolds the PA, one command starts a session, then the PA walks you through the rest.

## Prerequisites

Working installs of the following, then sign in to Claude Code:

- Node.js 24 or newer: https://nodejs.org (or your platform's Node 24 channel; on macOS `brew install node@24`)
- pnpm: https://pnpm.io/installation (or `brew install pnpm`)
- git: https://git-scm.com (or `brew install git`). `pa-init` runs `git init` inside the instance; you will need `user.name` and `user.email` set globally (via `git config --global user.name / user.email`) before your first commit, but the scaffold itself does not commit.
- Claude Code CLI: https://claude.ai/install (or `brew install --cask claude-code`). Run `claude` once, sign in, then Ctrl-C.

Do not install Claude Code with `npm -g` or `sudo npm -g`.

## 1. Scaffold the PA

Pick a `<pa-name>` in lowercase kebab-case (`alex`, `sam`, `hal-9000`). It becomes the agent directory and shows up in every log line.

```sh
npx -y -p @stravica-ai/digital-operator-pa@latest pa-init \
  --mode=solo \
  --name=<pa-name> \
  --operator="Your Name" \
  --target=$HOME/<pa-name>-instance \
  --non-interactive
```

That is the whole install. `pa-init` writes the instance under `$HOME/<pa-name>-instance`, pins the exact package version, runs `pnpm install`, and runs `pa status` to prove the install booted. It also seeds a `.session/onboarding.json` and a `/onboard` slash command so your PA can walk you through the rest on its first session.

Without flags, `npx -y @stravica-ai/digital-operator-pa@latest pa-init --mode=solo` prompts for each value.

## 2. Start a session and run /onboard

```sh
cd $HOME/<pa-name>-instance
pnpm exec pa session
```

Inside the session, type `/onboard`. The PA verifies the runtime, checks the installed version against npm, asks you a few profile questions, offers an optional shell alias, offers to start the local workspace, stands up the SOPS+age secrets vault when an enabled tool (Atlassian ships enabled by default) needs one, installs and proves the librarian distillation sweep as a mandatory step, and offers to wire up Atlassian (Jira, Confluence) if you use it. Every step is idempotent; re-run `/onboard` anytime to redo a specific step. Onboarding does not complete until the librarian schedule is installed and proven, and (when an enabled tool needs it) the vault is stood up. Those are the two pieces every solo instance needs so staged observations get distilled into knowledge and credentialed tools have somewhere to read their keys from.

## 3. Alias (optional)

`pa-init` prints the exact alias line at the end of a successful scaffold. Copy it into `~/.zshrc` or `~/.bashrc` and reload the shell:

```sh
alias <pa-name>='cd $HOME/<pa-name>-instance && pnpm exec pa session'
```

After that, typing `<pa-name>` from anywhere starts a session.

## What you get

- A generic Digital Operator operating model rendered into `agents/<pa-name>/CLAUDE.md` with a short root pointer at `CLAUDE.md`. Seven buckets, dispatch-first, autonomy envelope.
- The `pa` CLI: `status`, `session`, `workspace`, `project`, `work`, `knowledge`, `research`, `autonomy`, `environment`, `agent`, `lint`, `launch`, `gsc`.
- The read-only `desk` CLI: overview, today, projects, work.
- A local workspace server on `http://localhost:4200` (start with `pnpm exec pa workspace start`).
- A SIMPLE-mode local knowledge library: `pa knowledge search / related / domain / orphans / path / context`, seeded with the five base domains.
- Self-learning loop primitives: `agents/<pa-name>/staging/`, `journal.md`, `next-session.md`, `spawn-log.json`, autonomy envelope, and the Librarian distillation sweep, scaffolded as `schedules/<pa-name>-distillation-sweep.json` (every 4 hours) and installed by `/onboard` on the OS-native backend (launchd on macOS, cron on Linux). One immediate run is fired at install time so the ledger at `.cache/distill/logs/runs.jsonl` proves the schedule wiring end to end before onboarding completes.
- The `research` CLI with the light / normal / deep session store persisted under `.cache/research/`.
- Scheduler (cron on Linux, launchd on macOS): `pnpm exec scheduler --help`.
- Secrets vault (SOPS + age) if you opt in: `pnpm exec secrets --help`. The age private key lives INSIDE the instance at `.vault/age-key.txt` (gitignored) so a fresh solo instance beside another estate on the same laptop never touches, reads, or reuses the other estate's key. Delete the instance directory and the key goes with it; `pnpm exec secrets backup` is the way to take a portable copy first. The env override `SOPS_AGE_KEY_FILE` always wins for tests and one-off key-swap workflows; HQ-mode instances (only used inside a shared estate) keep today's per-user `~/.config/stravica-pa/age-key.txt` for cross-clone identity.
- `.claude/settings.json` with the `pa-coordinator-hook` wired in as a `PreToolUse` hook (inert until you export `PA_COORDINATOR_MODE=1`), a `SessionStart` hook that injects a live `distillationHealth` block at the top of every session (schedule state + last-run age + staging count), and `deep-research` denied at the permission layer.
- Two slash commands out of the box: `/research` (persisted research sessions) and `/onboard` (this walkthrough).
- Workspace-extension prompting: `operator/knowledge/platform-tooling/workspace-extensions.md` teaches your PA when to propose a workspace page and `pa-init workspace-extension <name>` scaffolds the HTML skeleton plus a `nav.json` entry. Add `--with-api` when the page needs a server route.

## rcf-lite: build small apps and services

Your PA has the `rcf-lite-engineer` role baked in. It builds greenfield applications from a weekend utility up to a small commercial SaaS, using the `rcf-lite` npm package as the spec-and-build spine (PRD, REQ, US, AC, FBS, with a green test suite gating each build). The link-led knowledge bucket at `operator/knowledge/rcf-lite/` seeds into every fresh solo instance and points at the current [Stravica RCF docs](https://stravica.ai/docs/rcf/); one local `create-a-small-app.md` walks a numbered command sequence from a fresh directory to a candidate build. Ask your PA to "build me a small app for X on rcf-lite" and it dispatches an `rcf-lite-engineer` instance with the deploy target, autonomy envelope, and RCF chain wired in.

## What is not included in solo mode

- **A full workState boot-context hook.** In some estates a `SessionStart` hook injects the live in-flight work items, active projects, and on-you list at the top of every session. Solo mode ships the narrower distillation-health hook (schedule + last-run + staging count) rather than a full workState block. If you want the broader one, extend `.claude/settings.json` with your own `SessionStart` hook.
- **Team modes.** `pa-init --mode=lead` and `--mode=member` exit with "not implemented". The SIMPLE-mode local library is single-operator by design.
- **Remote knowledge library.** The `remote` library mode requires a service on a persistent host, an age keypair, and a tunnel. Solo mode stays SIMPLE and runs entirely on your one laptop.
- **HQ-specialised roles.** The bundled role set is the core seven plus `product-engineer` and `rcf-lite-engineer` from the engineering types pack. Other tier-ladder roles and estate-specific extensions are not shipped.
- **Content publishing tool, Cloudflare / GSC live integrations, cross-host memory sync.** Out of scope for solo. Those all assume a multi-machine estate.

## Troubleshooting

- **`npx` cannot find `pa-init`.** Node 24 must be on your PATH; run `node -v` to confirm. On corporate networks a proxy may block the tarball download; a `pnpm setup` may also be needed if pnpm itself is not on PATH.
- **`pa status` reports a version older than `npm view @stravica-ai/digital-operator-pa version`.** Rare. `pa-init` pins the exact version and writes a `pnpm-workspace.yaml` with `minimumReleaseAgeExclude` inside the instance so pnpm's release-age gate cannot filter it out. If it still slips, run `pnpm install` inside the instance again to reconcile.
- **Do not put the instance under a directory that already contains a `pnpm-workspace.yaml`.** pnpm treats the instance as a workspace member, `pnpm install` silently no-ops, and `node_modules/.bin/pa` never appears. `$HOME/<pa-name>-instance` is safe.
- **Port 4200 already in use.** `pa workspace start --port N` picks a different port. `pa status` reads the resolved port from `operator/config/preferences.json` so keep the two in step across restarts.
- **`pa work create --status planned` is ignored on create.** The item lands as `draft`. Use `pa work status <id> planned` as a second step.
- **`LIBRARY_KNOWLEDGE_EXTRA_ROOTS`.** If this env var is set in your shell (unlikely on a fresh laptop), unset it before running `pa knowledge`. Set, it silently merges other knowledge trees into your local graph.
- **`pa workspace stop` on a machine that had the workspace daemon installed** refuses and points you at the `launchctl unload` or `systemctl --user stop` command in its own error message. `pa workspace restart` is the intended path. The daemon unit is `com.<paName>.workspace` (launchd) / `<paName>-workspace.service` (systemd).
- **CLAUDE.md updates.** Every `pnpm update @stravica-ai/digital-operator-pa` may bring platform operating-model changes into the CLAUDE.md template. The scaffold rendered your CLAUDE.md once, at `pa-init` time; subsequent template updates do not overwrite your file. Pin the package version and read the CHANGELOG before you upgrade.
- **`pnpm exec <tool>` run from a subdirectory of the instance can resolve a binary from another checkout on the same disk.** pnpm walks up looking for the nearest `node_modules`, and if another instance sits closer than yours, its binaries win. Run `pnpm exec` from the instance root, or invoke the binary by its installed path: `node node_modules/@stravica-ai/digital-operator-pa/bin/<tool>`. The release e2e (`pnpm run e2e:solo`) uses the second form for that reason.

## Why the single command works

`npx` fetches the tarball from npm, where there is no release-age gate. `pa-init` then writes the instance with an exact-pinned dependency plus a `pnpm-workspace.yaml` that carries `minimumReleaseAgeExclude: ["@stravica-ai/digital-operator-pa"]`, so the frozen `pnpm install` it runs next also lands on the exact version. Together they close the pnpm release-age hole that made the old bootstrap directory necessary in 0.1.41 / 0.1.42.

## Where things live

| What | Where |
|---|---|
| Root pointer | `CLAUDE.md` |
| Full operating instructions | `agents/<pa-name>/CLAUDE.md` |
| Operator profile | `operator/profile/profile.md` |
| Preferences | `operator/config/preferences.json` |
| Autonomy envelope | `agents/<pa-name>/autonomy-envelope.md` |
| Work items | `work/w-YYYY-MM-DD-<author>-NNN.json` |
| Projects | `projects/{id}/project.json` |
| Session environment | `.session/environment.json` |
| Onboarding state | `.session/onboarding.json` |
| Claude Code settings | `.claude/settings.json` |
| Coordinator-hook overlay | `.claude/coordinator-overlay.json` |
| Slash commands | `.claude/commands/` (`onboard.md`, `research.md`) |

## Removing an instance

Do everything below from inside the instance, in this order. Deleting the instance directory does not stop the workspace server, does not unload the launchd job (macOS) or cron entry (Linux) the scheduler registered, and does not remove the age key. A loaded schedule keeps firing against a path that no longer exists, its errors turn up in the system log with no easy trace back to the retired instance, and a running workspace server keeps its port bound after its own `node_modules` has been deleted.

The steps are ordered so that a stop or listing that fails does not orphan a running background process. If you already deleted the instance directory before reading this, jump to the fallbacks in step 1.

1. Stop the workspace server.
   ```
   pnpm exec pa workspace stop
   ```
   The stop command reads the pid and port from `.ws.pid` at the instance root, sends SIGTERM, and waits up to 5s before force-killing. Confirm with `pnpm exec pa workspace status`. If the instance directory is already gone (so `pnpm exec` is no longer runnable), find the process by port and kill it directly:
   ```
   cat .ws.pid                        # if .ws.pid still exists: {"pid":<N>,"port":<P>}
   lsof -i :<P> | grep LISTEN         # macOS/Linux: process holding the port
   pgrep -lf digital-operator-pa-workspace   # match the server's spawn command
   kill <pid>                         # SIGTERM; kill -9 <pid> if it refuses
   ```
   The server responds to `GET /__api/identity` with `{"server":"digital-operator-pa-workspace","repoRoot":"...","pid":<N>,...}`, so `curl -s http://127.0.0.1:<port>/__api/identity` will identify a rogue workspace server (and name the instance directory it was started from) before you kill it.

2. List every schedule the instance installed. Since 0.1.52 (w-2026-09-19-dave-001) the tool filters by this instance's `paName` from `operator/config/preferences.json`, so it only ever reports schedules that belong here:
   ```
   pnpm exec scheduler list
   ```
   The correct bin is `scheduler` (not `pa scheduler`; there is no `pa scheduler` subcommand). If the tool refuses because it cannot resolve a `paName`, pass `--agent <name>` explicitly.

3. Remove every id the list reports. `--delete-file` also removes the schedule JSON:
   ```
   pnpm exec scheduler remove <id> --delete-file
   ```
   Repeat per id.

4. Confirm nothing this instance registered is still loaded. On macOS, `launchctl list` and `crontab -l` should carry no entries with the `com.<paName>.` prefix respectively `# <paName>-` tag:
   ```
   launchctl list | grep "com.<paName>\."   # macOS
   crontab -l | grep "# <paName>-"           # cron backend
   systemctl --user list-timers | grep "<paName>-"   # linux/systemd
   ```

5. Only now delete the instance directory:
   ```
   rm -rf $HOME/<pa-name>-instance
   ```
   The age private key lives inside the instance at `.vault/age-key.txt` and goes with the directory. If you want a portable copy of the secrets first, run `pnpm exec secrets backup` from inside the instance BEFORE step 5.

6. Remove the Claude Code transcript directory. Session transcripts persist to `~/.claude/projects/<instance-path-slug>/*.jsonl` outside the instance directory, so deleting the instance does not remove them. Any operator input the transcript captured (including anything typed in chat during onboarding of instances predating 0.1.54) stays on disk in plaintext until this step runs:
   ```
   rm -rf "$HOME/.claude/projects/$(echo "$HOME/<pa-name>-instance" | sed 's|/|-|g')"
   ```
   Substitute `<pa-name>` from `operator/config/preferences.json`. On a fresh 0.1.54 onboarding, step 7 routes credentials to the workspace Secrets page or `secrets set KEY -`, so nothing token-shaped ever lands here. The directory is still worth removing for tidiness.
