@codyswann/lisa 2.140.0 → 2.141.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/package.json +1 -1
  2. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  3. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  4. package/plugins/lisa/skills/analyze-claude-remote/SKILL.md +109 -10
  5. package/plugins/lisa/skills/generate-claude-remote-build-script/SKILL.md +12 -2
  6. package/plugins/lisa-agy/plugin.json +1 -1
  7. package/plugins/lisa-agy/skills/analyze-claude-remote/SKILL.md +109 -10
  8. package/plugins/lisa-agy/skills/generate-claude-remote-build-script/SKILL.md +12 -2
  9. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  10. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  11. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  12. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  13. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  14. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  15. package/plugins/lisa-copilot/skills/analyze-claude-remote/SKILL.md +109 -10
  16. package/plugins/lisa-copilot/skills/generate-claude-remote-build-script/SKILL.md +12 -2
  17. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-cursor/skills/analyze-claude-remote/SKILL.md +109 -10
  19. package/plugins/lisa-cursor/skills/generate-claude-remote-build-script/SKILL.md +12 -2
  20. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  22. package/plugins/lisa-expo-agy/plugin.json +1 -1
  23. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  24. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  27. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  28. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  32. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  33. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  37. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  38. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  42. package/plugins/lisa-rails-agy/plugin.json +1 -1
  43. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  47. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  48. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  52. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  53. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  55. package/plugins/src/base/skills/analyze-claude-remote/SKILL.md +109 -10
  56. package/plugins/src/base/skills/generate-claude-remote-build-script/SKILL.md +12 -2
  57. package/scripts/claude-remote-setup.sh +114 -0
package/package.json CHANGED
@@ -84,7 +84,7 @@
84
84
  "lodash": ">=4.18.1"
85
85
  },
86
86
  "name": "@codyswann/lisa",
87
- "version": "2.140.0",
87
+ "version": "2.141.0",
88
88
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
89
89
  "main": "dist/index.js",
90
90
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.140.0",
3
+ "version": "2.141.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.140.0",
3
+ "version": "2.141.0",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: analyze-claude-remote
3
- description: "Audit whether the current repository can run as a Claude Code remote routine (cloud session). Read-only analysis that inventories what Lisa AND the host project need to configure or build in the cloud environment — external CLIs/binaries to install, environment variables and secrets to set, startup hooks and their headless-safety, MCP server scope/transport/auth, user-scoped config and auto-memory gaps that don't replicate to the cloud, and platform constraints (bun proxy, IP allowlist, network tier, no interactivity). Emits grouped findings plus a machine-readable inventory that /lisa:generate-claude-remote-build-script consumes."
3
+ description: "Audit whether the current repository can run as a Claude Code remote routine (cloud session). Read-only analysis that inventories what Lisa AND the host project need to configure or build in the cloud environment — external CLIs/binaries to install, environment variables and secrets to set, startup hooks and their headless-safety, MCP server scope/transport/auth, user-scoped config and auto-memory gaps that don't replicate to the cloud, and platform constraints (bun proxy, IP allowlist, network tier, no interactivity). Reads `.lisa.config.json` `tracker`/`source` to determine which tracker/PRD-source integrations are active, resolves each to its headless-viable substrate (CLI/curl + token, never browser-OAuth MCP, never OS-keychain), and spells out the exact secret env vars, where to obtain each token, and the precise access scope required — without guessing. Emits grouped findings plus a machine-readable inventory that /lisa:generate-claude-remote-build-script consumes."
4
4
  allowed-tools: ["Skill", "Bash", "Read", "Glob", "Grep"]
5
5
  ---
6
6
 
@@ -88,12 +88,46 @@ Group the findings as:
88
88
  in `.claude/settings.json` (e.g. `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS`) as `REQUIRED` to match
89
89
  local behavior, since the environment `env` block is the reliable place to set them.
90
90
 
91
+ 4a. **Tracker / PRD-source credentials** — this is the load-bearing part of the audit and must be
92
+ driven by config, not by what the scan happens to find. Resolve the active integrations first:
93
+
94
+ ```bash
95
+ TRACKER=$(jq -r '.tracker // "jira"' .lisa.config.json 2>/dev/null) # tickets: jira | github | linear
96
+ SOURCE=$(jq -r '.source // empty' .lisa.config.json 2>/dev/null) # PRDs: notion | confluence | github | linear
97
+ ```
98
+ (Apply `config-resolution`: `.lisa.config.local.json` overrides `.lisa.config.json`.) For the
99
+ **active** `tracker` and the **active** `source` — and only those — emit a `REQUIRED` credential
100
+ finding using the **Credential reference** table below. For every integration that is *not* the
101
+ active tracker/source, its credentials are `OPTIONAL` (dormant) — never mark them `REQUIRED`.
102
+
103
+ Two non-negotiable headless rules govern which substrate a routine can actually use:
104
+
105
+ - **Browser-OAuth MCP is dead headless.** A routine cannot complete an interactive OAuth/SSO
106
+ browser flow. So for any integration whose local substrate is an OAuth MCP (the committed
107
+ `linear-server` MCP; the Notion MCP; the Atlassian MCP) or an interactively-authed CLI
108
+ (`acli auth login --web`), the MCP/interactive tier is a `GAP` — the audit must route to that
109
+ integration's **token substrate** (CLI/curl + API token) and report the token's env vars.
110
+ - **OS keychain is absent headless.** Lisa's access skills read the token from the OS keychain
111
+ first (`security` / `secret-tool` / `cmdkey`) and fall back to an **env var**. A cloud routine
112
+ has no keyring daemon, so only the env-var fallback works. Always report the **env-var form**,
113
+ including the per-account suffixed names (`ATLASSIAN_API_TOKEN_<slug>`, `NOTION_API_TOKEN_<slug>`,
114
+ `LINEAR_API_KEY_<slug>`) when the integration keys tokens by email/workspace.
115
+
116
+ For each active integration, the finding must carry: the env var name(s), where to get the token
117
+ (`Acquire:` URL), and the **exact** access/scope required (`Access:`) — copied from the table, not
118
+ guessed. If a value the table needs (server URL, project key, workspace id, email, team key) is
119
+ missing from `.lisa.config.json`, flag it as a `GAP`/`Action:` to set it, rather than inventing one.
120
+
91
121
  5. **MCP servers** — read every committed `.mcp.json`. For each server report transport and auth.
92
- Project-scoped HTTP/SSE servers are `OK`. Flag stdio servers as `RISK`/`GAP` (need a local
93
- process — only viable if the cloud session can spawn them from the repo). Flag
94
- interactively/OAuth-authed servers (e.g. Linear) as `GAP` for first-time auth — they cannot
95
- complete a browser flow headless. Note any user-scoped MCP (`~/.claude.json`) as `GAP` it
96
- never reaches the cloud; it must be moved into project `.mcp.json`.
122
+ Project-scoped HTTP/SSE servers with no interactive auth are `OK`. Flag stdio servers as
123
+ `RISK`/`GAP` (need a local process — only viable if the cloud session can spawn them from the
124
+ repo). Flag interactively/OAuth-authed servers as `GAP` for headless auth — they cannot complete
125
+ a browser flow headless **regardless of transport** (an HTTP MCP like `linear-server` is still a
126
+ `GAP` because its *auth* is OAuth, not because of its transport). When an OAuth MCP backs an
127
+ active tracker/source, do not stop at the `GAP` — cross-reference group 4a and point to the
128
+ integration's token substrate as the headless replacement (e.g. `linear-server` MCP → `LINEAR_API_KEY`
129
+ + Linear GraphQL). Note any user-scoped MCP (`~/.claude.json`) as `GAP` — it never reaches the
130
+ cloud; it must be moved into project `.mcp.json`.
97
131
 
98
132
  6. **Config scope & memory gaps** — identify reliance on user-scoped config that will not load
99
133
  remotely: `~/.claude/CLAUDE.md`, user `enabledPlugins`, user skills/agents, user MCP. Most
@@ -112,6 +146,46 @@ Group the findings as:
112
146
  runtime service it depends on (database, queue, external API) that will not exist in a fresh
113
147
  cloud environment, so the user can decide whether the routine's task is even feasible there.
114
148
 
149
+ ## Credential reference (tracker / source → headless secret)
150
+
151
+ Authoritative mapping for group 4a, transcribed from Lisa's `setup-*` skills and access layers
152
+ (`setup-github`, `setup-atlassian`, `setup-jira`, `setup-notion`, `setup-linear`,
153
+ `atlassian-access`, `notion-access`). Use the row for the **active** `tracker`/`source` only. Report
154
+ the **env-var form** of each secret — keychain reads do not work in a cloud routine. Slugs:
155
+ `<email-slug>` = email via `tr '[:upper:]@.' '[:lower:]__'`; `<ws-slug>` = workspace via
156
+ `tr '[:upper:]-' '[:lower:]_'`. If a token has both an unsuffixed and a per-account form, the
157
+ unsuffixed `…_TOKEN`/`…_KEY` is the simplest to set in a single-account routine.
158
+
159
+ ### GitHub — `tracker: github` and/or `source: github`
160
+ - Headless substrate: `gh` CLI authed by token (every Lisa GitHub script gates on `gh auth status`).
161
+ - Env: `GH_TOKEN` (the routine's built-in repo connection may not authenticate the `gh` CLI — verify; set `GH_TOKEN` if `gh auth status` fails). `PAT` only for cross-repo flows.
162
+ - Acquire: fine-grained — `https://github.com/settings/personal-access-tokens`; classic — `https://github.com/settings/tokens`.
163
+ - Access: fine-grained → Repository access to the target repo(s); Repository permissions: Contents R/W, Issues R/W, Pull requests R/W, Metadata R (mandatory); add Workflows R/W only if editing `.github/workflows`, and Organization → Projects R/W only if using ProjectV2. Classic equivalent: `repo` + `workflow` (+ `project`, `read:org` for boards). The identity must hold WRITE/MAINTAIN/ADMIN on the repo.
164
+
165
+ ### JIRA — `tracker: jira`
166
+ - Headless substrate: `jira-cli` + curl (Basic auth). The acli and Atlassian-MCP tiers need prior interactive/OAuth auth → not viable headless.
167
+ - Env: `JIRA_API_TOKEN`, `JIRA_SERVER` (e.g. `https://acme.atlassian.net`), `JIRA_LOGIN` (account email), `JIRA_PROJECT` (default project key); optional `JIRA_INSTALLATION` (default `cloud`), `JIRA_BOARD`. (`setup-jira-cli.sh` writes the jira-cli config from these on SessionStart.)
168
+ - Acquire: `https://id.atlassian.com/manage-profile/security/api-tokens`.
169
+ - Access: the API token inherits the Atlassian user's permissions — the user must have Browse/Create/Edit/Transition on the target project. An unscoped token suffices for jira-cli; a scoped token must cover the JIRA project read/write operations.
170
+
171
+ ### Confluence — `source: confluence`
172
+ - Headless substrate: curl + Basic auth + **scoped** API token.
173
+ - Env: `ATLASSIAN_API_TOKEN` (or per-account `ATLASSIAN_API_TOKEN_<email-slug>`). Config (`.lisa.config.json`): `atlassian.cloudId`, `atlassian.site`, `atlassian.email`.
174
+ - Acquire: `https://id.atlassian.com/manage-profile/security/api-tokens` → "Create API token **with scopes**" → App: **Confluence**.
175
+ - Access (select EXACTLY): `read:page:confluence`, `read:hierarchical-content:confluence`, `read:comment:confluence`, `read:space:confluence`, `write:page:confluence`, `write:comment:confluence`, `write:label:confluence`, `search:confluence`.
176
+
177
+ ### Notion — `source: notion`
178
+ - Headless substrate: curl + Bearer + internal-integration token. The Notion MCP tier is OAuth → not viable headless.
179
+ - Env: `NOTION_API_TOKEN` (or per-account `NOTION_API_TOKEN_<ws-slug>`). Config: `notion.workspaceId`, `notion.prdDatabaseId`.
180
+ - Acquire: `https://www.notion.so/profile/integrations` → New integration → type **Internal** → copy the `ntn_*` Internal Integration Token.
181
+ - Access: internal-integration token. **Non-optional:** share the target PRD database with the integration (Notion's share-based model) or every call returns 404/`object_not_found`.
182
+
183
+ ### Linear — `tracker: linear` and/or `source: linear`
184
+ - Headless substrate: curl GraphQL (`https://api.linear.app/graphql`) + personal API key. The committed `linear-server` MCP is OAuth/browser → cannot authenticate headless; the API key is the only headless path.
185
+ - Env: `LINEAR_API_KEY` (or per-account `LINEAR_API_KEY_<ws-slug>`). Config: `linear.workspace`; `linear.teamKey` required when Linear is the tracker.
186
+ - Acquire: `https://linear.app/<workspace>/settings/account/security` → Personal API keys → New API key.
187
+ - Access: the personal API key inherits the user's workspace permissions — the user must be able to read/create/update Issues in the destination team.
188
+
115
189
  ## Output
116
190
 
117
191
  Render the report grouped exactly as above. Start with one `Summary:` line, then a `Counts:` line
@@ -120,8 +194,17 @@ line per check as `- <STATUS> <id>: <summary>`, with optional `Observed:` and `A
120
194
  beneath that separate fact from advice. Render an empty group as a single `OK`/`SKIP` line with the
121
195
  reason rather than omitting it.
122
196
 
197
+ Immediately after the grouped findings, render a **`Credentials to provision`** subsection — a
198
+ checklist of the secrets the user must set in the routine's environment for the **active**
199
+ `tracker`/`source` (from group 4a). One block per active integration, each with its env-var name(s),
200
+ an `Acquire:` URL, and an `Access:` scope line, plus a one-line note that the environment UI is where
201
+ these are set (the generated build script only emits a names-only template, never values). If both
202
+ `tracker` and `source` resolve to the same vendor (e.g. both `github`), render it once.
203
+
123
204
  End with a fenced, machine-readable inventory block (also printed when `--json` is passed) so
124
- `/lisa:generate-claude-remote-build-script` can consume it without re-deriving everything:
205
+ `/lisa:generate-claude-remote-build-script` can consume it without re-deriving everything. Secret
206
+ `env` entries for active integrations MUST carry `acquireUrl`, `accessScope`, and `headlessSubstrate`
207
+ so the generator can render acquisition comments into its template:
125
208
 
126
209
  ```json
127
210
  {
@@ -130,12 +213,22 @@ End with a fenced, machine-readable inventory block (also printed when `--json`
130
213
  { "name": "gh", "required": true, "reason": "github-* skills and scripts shell out to gh" },
131
214
  { "name": "jq", "required": true, "reason": "hooks and scripts parse JSON" }
132
215
  ],
216
+ "tracker": "github",
217
+ "source": "github",
133
218
  "env": [
134
219
  { "name": "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS", "required": true, "secret": false, "reason": "set in .claude/settings.json" },
135
- { "name": "GH_TOKEN", "required": false, "secret": true, "reason": "gh CLI auth beyond the routine's repo connection" }
220
+ {
221
+ "name": "GH_TOKEN", "required": true, "secret": true, "integration": "github",
222
+ "reason": "active tracker+source; gh scripts gate on gh auth status",
223
+ "headlessSubstrate": "gh CLI (token)",
224
+ "acquireUrl": "https://github.com/settings/personal-access-tokens",
225
+ "accessScope": "fine-grained PAT on target repo: Contents R/W, Issues R/W, Pull requests R/W, Metadata R; +Workflows R/W if editing .github/workflows; +Projects R/W if using ProjectV2"
226
+ }
227
+ ],
228
+ "mcp": [
229
+ { "name": "linear-server", "transport": "http", "auth": "oauth", "headlessUsable": false, "replacedBy": "LINEAR_API_KEY + Linear GraphQL", "dormant": true }
136
230
  ],
137
- "mcp": [ { "name": "linear-server", "transport": "http", "authGap": true } ],
138
- "gaps": [ "auto-memory not synced to cloud", "bun package fetch behind proxy" ],
231
+ "gaps": [ "auto-memory not synced to cloud", "bun package fetch behind proxy", "OS keychain absent — env-var token form only" ],
139
232
  "allowlistDomains": []
140
233
  }
141
234
  ```
@@ -159,3 +252,9 @@ End with a fenced, machine-readable inventory block (also printed when `--json`
159
252
  - Never report a `GAP` as satisfiable by configuration — a gap is a constraint, and the action must
160
253
  be a change of approach, not "set an env var".
161
254
  - Never invent tools or env vars that no committed file references.
255
+ - Credential scopes and acquisition URLs come from the **Credential reference** table (sourced from
256
+ Lisa's `setup-*` skills) — transcribe them exactly; never guess at the access a token needs.
257
+ - For the active `tracker`/`source`, always report the **env-var** form of the secret, never the OS
258
+ keychain form — keychain reads do not work in a cloud routine.
259
+ - A browser-OAuth MCP (or interactively-authed CLI) backing an active integration is a `GAP`; the
260
+ remediation is its token substrate from the table, not "authenticate the MCP".
@@ -53,7 +53,12 @@ tracker/source, plus the host project's own package manager and tooling — not
53
53
  with the reason. **Never write real secret values** — only names and placeholders, because the
54
54
  environment config is visible to anyone who can edit it. Include feature flags actually set in
55
55
  `.claude/settings.json` (e.g. `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS`) so cloud behavior matches
56
- local.
56
+ local. For every secret entry that carries `acquireUrl`/`accessScope`/`headlessSubstrate` (the
57
+ active tracker/source credentials from the analysis's group 4a), render those as comment lines
58
+ directly above the name — `# Acquire: <url>` and `# Access: <scope>` — so the user knows exactly
59
+ where to get the token and what permissions it needs. Emit only the **env-var form** of the name
60
+ that the analysis reported (including any per-account suffixed form like `LINEAR_API_KEY_<slug>`);
61
+ never emit a keychain instruction — keychain does not exist in a cloud routine.
57
62
 
58
63
  4. **Emit the allowlist + gaps notice.** List any custom domains the setup or runtime reaches
59
64
  (from `allowlistDomains`) that the user must add to the environment's network access, and echo
@@ -80,7 +85,10 @@ shape, not a fixed payload):
80
85
  # - <gaps from analysis, e.g. auto-memory is machine-local and not synced to cloud routines>
81
86
  # ENV VARS to set in the environment config (names only — set real values there, not here):
82
87
  # - CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 # REQUIRED, matches .claude/settings.json
83
- # - GH_TOKEN=<token> # OPTIONAL, gh auth beyond the repo connection
88
+ # # --- credentials for the active tracker/source (set in the environment UI) ---
89
+ # # Acquire: https://github.com/settings/personal-access-tokens
90
+ # # Access: fine-grained PAT on target repo: Contents R/W, Issues R/W, Pull requests R/W, Metadata R
91
+ # - GH_TOKEN=<token> # REQUIRED, github is the active tracker+source
84
92
  # NETWORK: allowlist these domains in the environment if not on full access:
85
93
  # - <allowlistDomains, if any>
86
94
  set -uo pipefail
@@ -116,6 +124,8 @@ to stop are: the analysis could not run, or the `--out` path is not writable.
116
124
  - Always derive the script from a fresh `/lisa:analyze-claude-remote` run — never from a stale or
117
125
  assumed inventory.
118
126
  - Never write real secret values into the script or template — names and placeholders only.
127
+ - For active tracker/source credentials, carry the analysis's `Acquire:` URL and `Access:` scope into
128
+ the template as comments, and emit only the env-var form of the name — never a keychain command.
119
129
  - Never emit an install for a tool the analysis did not surface, and never install `OPTIONAL` tools
120
130
  unless `--include-optional` is set.
121
131
  - Keep the script idempotent and detect-before-install so it is safe to re-run and cache.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.140.0",
3
+ "version": "2.141.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: analyze-claude-remote
3
- description: "Audit whether the current repository can run as a Claude Code remote routine (cloud session). Read-only analysis that inventories what Lisa AND the host project need to configure or build in the cloud environment — external CLIs/binaries to install, environment variables and secrets to set, startup hooks and their headless-safety, MCP server scope/transport/auth, user-scoped config and auto-memory gaps that don't replicate to the cloud, and platform constraints (bun proxy, IP allowlist, network tier, no interactivity). Emits grouped findings plus a machine-readable inventory that /lisa:generate-claude-remote-build-script consumes."
3
+ description: "Audit whether the current repository can run as a Claude Code remote routine (cloud session). Read-only analysis that inventories what Lisa AND the host project need to configure or build in the cloud environment — external CLIs/binaries to install, environment variables and secrets to set, startup hooks and their headless-safety, MCP server scope/transport/auth, user-scoped config and auto-memory gaps that don't replicate to the cloud, and platform constraints (bun proxy, IP allowlist, network tier, no interactivity). Reads `.lisa.config.json` `tracker`/`source` to determine which tracker/PRD-source integrations are active, resolves each to its headless-viable substrate (CLI/curl + token, never browser-OAuth MCP, never OS-keychain), and spells out the exact secret env vars, where to obtain each token, and the precise access scope required — without guessing. Emits grouped findings plus a machine-readable inventory that /lisa:generate-claude-remote-build-script consumes."
4
4
  allowed-tools: ["Skill", "Bash", "Read", "Glob", "Grep"]
5
5
  ---
6
6
 
@@ -88,12 +88,46 @@ Group the findings as:
88
88
  in `.claude/settings.json` (e.g. `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS`) as `REQUIRED` to match
89
89
  local behavior, since the environment `env` block is the reliable place to set them.
90
90
 
91
+ 4a. **Tracker / PRD-source credentials** — this is the load-bearing part of the audit and must be
92
+ driven by config, not by what the scan happens to find. Resolve the active integrations first:
93
+
94
+ ```bash
95
+ TRACKER=$(jq -r '.tracker // "jira"' .lisa.config.json 2>/dev/null) # tickets: jira | github | linear
96
+ SOURCE=$(jq -r '.source // empty' .lisa.config.json 2>/dev/null) # PRDs: notion | confluence | github | linear
97
+ ```
98
+ (Apply `config-resolution`: `.lisa.config.local.json` overrides `.lisa.config.json`.) For the
99
+ **active** `tracker` and the **active** `source` — and only those — emit a `REQUIRED` credential
100
+ finding using the **Credential reference** table below. For every integration that is *not* the
101
+ active tracker/source, its credentials are `OPTIONAL` (dormant) — never mark them `REQUIRED`.
102
+
103
+ Two non-negotiable headless rules govern which substrate a routine can actually use:
104
+
105
+ - **Browser-OAuth MCP is dead headless.** A routine cannot complete an interactive OAuth/SSO
106
+ browser flow. So for any integration whose local substrate is an OAuth MCP (the committed
107
+ `linear-server` MCP; the Notion MCP; the Atlassian MCP) or an interactively-authed CLI
108
+ (`acli auth login --web`), the MCP/interactive tier is a `GAP` — the audit must route to that
109
+ integration's **token substrate** (CLI/curl + API token) and report the token's env vars.
110
+ - **OS keychain is absent headless.** Lisa's access skills read the token from the OS keychain
111
+ first (`security` / `secret-tool` / `cmdkey`) and fall back to an **env var**. A cloud routine
112
+ has no keyring daemon, so only the env-var fallback works. Always report the **env-var form**,
113
+ including the per-account suffixed names (`ATLASSIAN_API_TOKEN_<slug>`, `NOTION_API_TOKEN_<slug>`,
114
+ `LINEAR_API_KEY_<slug>`) when the integration keys tokens by email/workspace.
115
+
116
+ For each active integration, the finding must carry: the env var name(s), where to get the token
117
+ (`Acquire:` URL), and the **exact** access/scope required (`Access:`) — copied from the table, not
118
+ guessed. If a value the table needs (server URL, project key, workspace id, email, team key) is
119
+ missing from `.lisa.config.json`, flag it as a `GAP`/`Action:` to set it, rather than inventing one.
120
+
91
121
  5. **MCP servers** — read every committed `.mcp.json`. For each server report transport and auth.
92
- Project-scoped HTTP/SSE servers are `OK`. Flag stdio servers as `RISK`/`GAP` (need a local
93
- process — only viable if the cloud session can spawn them from the repo). Flag
94
- interactively/OAuth-authed servers (e.g. Linear) as `GAP` for first-time auth — they cannot
95
- complete a browser flow headless. Note any user-scoped MCP (`~/.claude.json`) as `GAP` it
96
- never reaches the cloud; it must be moved into project `.mcp.json`.
122
+ Project-scoped HTTP/SSE servers with no interactive auth are `OK`. Flag stdio servers as
123
+ `RISK`/`GAP` (need a local process — only viable if the cloud session can spawn them from the
124
+ repo). Flag interactively/OAuth-authed servers as `GAP` for headless auth — they cannot complete
125
+ a browser flow headless **regardless of transport** (an HTTP MCP like `linear-server` is still a
126
+ `GAP` because its *auth* is OAuth, not because of its transport). When an OAuth MCP backs an
127
+ active tracker/source, do not stop at the `GAP` — cross-reference group 4a and point to the
128
+ integration's token substrate as the headless replacement (e.g. `linear-server` MCP → `LINEAR_API_KEY`
129
+ + Linear GraphQL). Note any user-scoped MCP (`~/.claude.json`) as `GAP` — it never reaches the
130
+ cloud; it must be moved into project `.mcp.json`.
97
131
 
98
132
  6. **Config scope & memory gaps** — identify reliance on user-scoped config that will not load
99
133
  remotely: `~/.claude/CLAUDE.md`, user `enabledPlugins`, user skills/agents, user MCP. Most
@@ -112,6 +146,46 @@ Group the findings as:
112
146
  runtime service it depends on (database, queue, external API) that will not exist in a fresh
113
147
  cloud environment, so the user can decide whether the routine's task is even feasible there.
114
148
 
149
+ ## Credential reference (tracker / source → headless secret)
150
+
151
+ Authoritative mapping for group 4a, transcribed from Lisa's `setup-*` skills and access layers
152
+ (`setup-github`, `setup-atlassian`, `setup-jira`, `setup-notion`, `setup-linear`,
153
+ `atlassian-access`, `notion-access`). Use the row for the **active** `tracker`/`source` only. Report
154
+ the **env-var form** of each secret — keychain reads do not work in a cloud routine. Slugs:
155
+ `<email-slug>` = email via `tr '[:upper:]@.' '[:lower:]__'`; `<ws-slug>` = workspace via
156
+ `tr '[:upper:]-' '[:lower:]_'`. If a token has both an unsuffixed and a per-account form, the
157
+ unsuffixed `…_TOKEN`/`…_KEY` is the simplest to set in a single-account routine.
158
+
159
+ ### GitHub — `tracker: github` and/or `source: github`
160
+ - Headless substrate: `gh` CLI authed by token (every Lisa GitHub script gates on `gh auth status`).
161
+ - Env: `GH_TOKEN` (the routine's built-in repo connection may not authenticate the `gh` CLI — verify; set `GH_TOKEN` if `gh auth status` fails). `PAT` only for cross-repo flows.
162
+ - Acquire: fine-grained — `https://github.com/settings/personal-access-tokens`; classic — `https://github.com/settings/tokens`.
163
+ - Access: fine-grained → Repository access to the target repo(s); Repository permissions: Contents R/W, Issues R/W, Pull requests R/W, Metadata R (mandatory); add Workflows R/W only if editing `.github/workflows`, and Organization → Projects R/W only if using ProjectV2. Classic equivalent: `repo` + `workflow` (+ `project`, `read:org` for boards). The identity must hold WRITE/MAINTAIN/ADMIN on the repo.
164
+
165
+ ### JIRA — `tracker: jira`
166
+ - Headless substrate: `jira-cli` + curl (Basic auth). The acli and Atlassian-MCP tiers need prior interactive/OAuth auth → not viable headless.
167
+ - Env: `JIRA_API_TOKEN`, `JIRA_SERVER` (e.g. `https://acme.atlassian.net`), `JIRA_LOGIN` (account email), `JIRA_PROJECT` (default project key); optional `JIRA_INSTALLATION` (default `cloud`), `JIRA_BOARD`. (`setup-jira-cli.sh` writes the jira-cli config from these on SessionStart.)
168
+ - Acquire: `https://id.atlassian.com/manage-profile/security/api-tokens`.
169
+ - Access: the API token inherits the Atlassian user's permissions — the user must have Browse/Create/Edit/Transition on the target project. An unscoped token suffices for jira-cli; a scoped token must cover the JIRA project read/write operations.
170
+
171
+ ### Confluence — `source: confluence`
172
+ - Headless substrate: curl + Basic auth + **scoped** API token.
173
+ - Env: `ATLASSIAN_API_TOKEN` (or per-account `ATLASSIAN_API_TOKEN_<email-slug>`). Config (`.lisa.config.json`): `atlassian.cloudId`, `atlassian.site`, `atlassian.email`.
174
+ - Acquire: `https://id.atlassian.com/manage-profile/security/api-tokens` → "Create API token **with scopes**" → App: **Confluence**.
175
+ - Access (select EXACTLY): `read:page:confluence`, `read:hierarchical-content:confluence`, `read:comment:confluence`, `read:space:confluence`, `write:page:confluence`, `write:comment:confluence`, `write:label:confluence`, `search:confluence`.
176
+
177
+ ### Notion — `source: notion`
178
+ - Headless substrate: curl + Bearer + internal-integration token. The Notion MCP tier is OAuth → not viable headless.
179
+ - Env: `NOTION_API_TOKEN` (or per-account `NOTION_API_TOKEN_<ws-slug>`). Config: `notion.workspaceId`, `notion.prdDatabaseId`.
180
+ - Acquire: `https://www.notion.so/profile/integrations` → New integration → type **Internal** → copy the `ntn_*` Internal Integration Token.
181
+ - Access: internal-integration token. **Non-optional:** share the target PRD database with the integration (Notion's share-based model) or every call returns 404/`object_not_found`.
182
+
183
+ ### Linear — `tracker: linear` and/or `source: linear`
184
+ - Headless substrate: curl GraphQL (`https://api.linear.app/graphql`) + personal API key. The committed `linear-server` MCP is OAuth/browser → cannot authenticate headless; the API key is the only headless path.
185
+ - Env: `LINEAR_API_KEY` (or per-account `LINEAR_API_KEY_<ws-slug>`). Config: `linear.workspace`; `linear.teamKey` required when Linear is the tracker.
186
+ - Acquire: `https://linear.app/<workspace>/settings/account/security` → Personal API keys → New API key.
187
+ - Access: the personal API key inherits the user's workspace permissions — the user must be able to read/create/update Issues in the destination team.
188
+
115
189
  ## Output
116
190
 
117
191
  Render the report grouped exactly as above. Start with one `Summary:` line, then a `Counts:` line
@@ -120,8 +194,17 @@ line per check as `- <STATUS> <id>: <summary>`, with optional `Observed:` and `A
120
194
  beneath that separate fact from advice. Render an empty group as a single `OK`/`SKIP` line with the
121
195
  reason rather than omitting it.
122
196
 
197
+ Immediately after the grouped findings, render a **`Credentials to provision`** subsection — a
198
+ checklist of the secrets the user must set in the routine's environment for the **active**
199
+ `tracker`/`source` (from group 4a). One block per active integration, each with its env-var name(s),
200
+ an `Acquire:` URL, and an `Access:` scope line, plus a one-line note that the environment UI is where
201
+ these are set (the generated build script only emits a names-only template, never values). If both
202
+ `tracker` and `source` resolve to the same vendor (e.g. both `github`), render it once.
203
+
123
204
  End with a fenced, machine-readable inventory block (also printed when `--json` is passed) so
124
- `/lisa:generate-claude-remote-build-script` can consume it without re-deriving everything:
205
+ `/lisa:generate-claude-remote-build-script` can consume it without re-deriving everything. Secret
206
+ `env` entries for active integrations MUST carry `acquireUrl`, `accessScope`, and `headlessSubstrate`
207
+ so the generator can render acquisition comments into its template:
125
208
 
126
209
  ```json
127
210
  {
@@ -130,12 +213,22 @@ End with a fenced, machine-readable inventory block (also printed when `--json`
130
213
  { "name": "gh", "required": true, "reason": "github-* skills and scripts shell out to gh" },
131
214
  { "name": "jq", "required": true, "reason": "hooks and scripts parse JSON" }
132
215
  ],
216
+ "tracker": "github",
217
+ "source": "github",
133
218
  "env": [
134
219
  { "name": "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS", "required": true, "secret": false, "reason": "set in .claude/settings.json" },
135
- { "name": "GH_TOKEN", "required": false, "secret": true, "reason": "gh CLI auth beyond the routine's repo connection" }
220
+ {
221
+ "name": "GH_TOKEN", "required": true, "secret": true, "integration": "github",
222
+ "reason": "active tracker+source; gh scripts gate on gh auth status",
223
+ "headlessSubstrate": "gh CLI (token)",
224
+ "acquireUrl": "https://github.com/settings/personal-access-tokens",
225
+ "accessScope": "fine-grained PAT on target repo: Contents R/W, Issues R/W, Pull requests R/W, Metadata R; +Workflows R/W if editing .github/workflows; +Projects R/W if using ProjectV2"
226
+ }
227
+ ],
228
+ "mcp": [
229
+ { "name": "linear-server", "transport": "http", "auth": "oauth", "headlessUsable": false, "replacedBy": "LINEAR_API_KEY + Linear GraphQL", "dormant": true }
136
230
  ],
137
- "mcp": [ { "name": "linear-server", "transport": "http", "authGap": true } ],
138
- "gaps": [ "auto-memory not synced to cloud", "bun package fetch behind proxy" ],
231
+ "gaps": [ "auto-memory not synced to cloud", "bun package fetch behind proxy", "OS keychain absent — env-var token form only" ],
139
232
  "allowlistDomains": []
140
233
  }
141
234
  ```
@@ -159,3 +252,9 @@ End with a fenced, machine-readable inventory block (also printed when `--json`
159
252
  - Never report a `GAP` as satisfiable by configuration — a gap is a constraint, and the action must
160
253
  be a change of approach, not "set an env var".
161
254
  - Never invent tools or env vars that no committed file references.
255
+ - Credential scopes and acquisition URLs come from the **Credential reference** table (sourced from
256
+ Lisa's `setup-*` skills) — transcribe them exactly; never guess at the access a token needs.
257
+ - For the active `tracker`/`source`, always report the **env-var** form of the secret, never the OS
258
+ keychain form — keychain reads do not work in a cloud routine.
259
+ - A browser-OAuth MCP (or interactively-authed CLI) backing an active integration is a `GAP`; the
260
+ remediation is its token substrate from the table, not "authenticate the MCP".
@@ -53,7 +53,12 @@ tracker/source, plus the host project's own package manager and tooling — not
53
53
  with the reason. **Never write real secret values** — only names and placeholders, because the
54
54
  environment config is visible to anyone who can edit it. Include feature flags actually set in
55
55
  `.claude/settings.json` (e.g. `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS`) so cloud behavior matches
56
- local.
56
+ local. For every secret entry that carries `acquireUrl`/`accessScope`/`headlessSubstrate` (the
57
+ active tracker/source credentials from the analysis's group 4a), render those as comment lines
58
+ directly above the name — `# Acquire: <url>` and `# Access: <scope>` — so the user knows exactly
59
+ where to get the token and what permissions it needs. Emit only the **env-var form** of the name
60
+ that the analysis reported (including any per-account suffixed form like `LINEAR_API_KEY_<slug>`);
61
+ never emit a keychain instruction — keychain does not exist in a cloud routine.
57
62
 
58
63
  4. **Emit the allowlist + gaps notice.** List any custom domains the setup or runtime reaches
59
64
  (from `allowlistDomains`) that the user must add to the environment's network access, and echo
@@ -80,7 +85,10 @@ shape, not a fixed payload):
80
85
  # - <gaps from analysis, e.g. auto-memory is machine-local and not synced to cloud routines>
81
86
  # ENV VARS to set in the environment config (names only — set real values there, not here):
82
87
  # - CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 # REQUIRED, matches .claude/settings.json
83
- # - GH_TOKEN=<token> # OPTIONAL, gh auth beyond the repo connection
88
+ # # --- credentials for the active tracker/source (set in the environment UI) ---
89
+ # # Acquire: https://github.com/settings/personal-access-tokens
90
+ # # Access: fine-grained PAT on target repo: Contents R/W, Issues R/W, Pull requests R/W, Metadata R
91
+ # - GH_TOKEN=<token> # REQUIRED, github is the active tracker+source
84
92
  # NETWORK: allowlist these domains in the environment if not on full access:
85
93
  # - <allowlistDomains, if any>
86
94
  set -uo pipefail
@@ -116,6 +124,8 @@ to stop are: the analysis could not run, or the `--out` path is not writable.
116
124
  - Always derive the script from a fresh `/lisa:analyze-claude-remote` run — never from a stale or
117
125
  assumed inventory.
118
126
  - Never write real secret values into the script or template — names and placeholders only.
127
+ - For active tracker/source credentials, carry the analysis's `Acquire:` URL and `Access:` scope into
128
+ the template as comments, and emit only the env-var form of the name — never a keychain command.
119
129
  - Never emit an install for a tool the analysis did not surface, and never install `OPTIONAL` tools
120
130
  unless `--include-optional` is set.
121
131
  - Keep the script idempotent and detect-before-install so it is safe to re-run and cache.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.140.0",
3
+ "version": "2.141.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.140.0",
3
+ "version": "2.141.0",
4
4
  "description": "AWS CDK-specific Lisa plugin.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.140.0",
3
+ "version": "2.141.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.140.0",
3
+ "version": "2.141.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.140.0",
3
+ "version": "2.141.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.140.0",
3
+ "version": "2.141.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"