@codyswann/lisa 2.338.4 → 2.338.5

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 (72) hide show
  1. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  2. package/dist/core/upstream-evidence-manifest.js +4 -3
  3. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  4. package/package.json +1 -1
  5. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  6. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  7. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/providers.mjs +23 -0
  8. package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/surfaces.mjs +7 -1
  9. package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +117 -8
  10. package/plugins/lisa/skills/lisa-secrets-access/scripts/providers.mjs +23 -0
  11. package/plugins/lisa/skills/lisa-secrets-access/scripts/surfaces.mjs +7 -1
  12. package/plugins/lisa/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +117 -8
  13. package/plugins/lisa-agy/plugin.json +1 -1
  14. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/providers.mjs +23 -0
  15. package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/surfaces.mjs +7 -1
  16. package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +117 -8
  17. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  19. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  20. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  22. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/providers.mjs +23 -0
  24. package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/surfaces.mjs +7 -1
  25. package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +117 -8
  26. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  27. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/providers.mjs +23 -0
  28. package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/surfaces.mjs +7 -1
  29. package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +117 -8
  30. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  32. package/plugins/lisa-expo-agy/plugin.json +1 -1
  33. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  37. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  38. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  42. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  43. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  47. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  48. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  52. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  53. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  57. package/plugins/lisa-rails-agy/plugin.json +1 -1
  58. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  62. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  63. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  67. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  68. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  70. package/plugins/src/base/skills/lisa-secrets-access/scripts/providers.mjs +23 -0
  71. package/plugins/src/base/skills/lisa-secrets-access/scripts/surfaces.mjs +7 -1
  72. package/plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +117 -8
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Expo and React Native-specific skills, agents, rules, and MCP servers.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Harper/Fabric-specific Lisa rules for TypeScript component apps.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "NestJS-specific skills and migration write-protection hooks.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Ruby on Rails-specific skills and hooks for RuboCop and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "TypeScript-specific hooks for formatting, linting, and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "Distributable LLM Wiki kernel — ingest, query, lint, and maintain a git-native markdown knowledge base across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.338.4",
3
+ "version": "2.338.5",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -51,6 +51,29 @@ const PROVIDER_BOOTSTRAP_ENV = {
51
51
  doppler: "DOPPLER_TOKEN",
52
52
  };
53
53
 
54
+ /**
55
+ * The tenant-scoped bootstrap variable a provider expects, by convention.
56
+ *
57
+ * Exists so the repo-less path cannot invent one. It used to compose
58
+ * `BWS_ACCESS_TOKEN_<namespace>` literally, ignoring the provider it had just
59
+ * resolved — so a Doppler tenant with no checkout was told to set a Bitwarden
60
+ * variable, and its CLI failed with "Missing access token". That is precisely
61
+ * the confusion the two questions above are separated to prevent, reintroduced
62
+ * on the one surface with no config file to correct it.
63
+ *
64
+ * `null` for a provider with no env-var bootstrap — 1Password, Vault and AWS
65
+ * authenticate by other means — because a name invented for them would be a
66
+ * variable nothing reads, which is worse than admitting there is none.
67
+ * `providerEnv` already treats an unmapped provider as "inject nothing".
68
+ * @param {string} provider Provider name.
69
+ * @param {string} namespace Tenant namespace.
70
+ * @returns {string|null} The variable to set, or null when the provider has none.
71
+ */
72
+ export function bootstrapKeyFor(provider, namespace) {
73
+ const canonical = PROVIDER_BOOTSTRAP_ENV[provider];
74
+ return canonical ? `${canonical}_${namespace}` : null;
75
+ }
76
+
54
77
  /**
55
78
  * Build the child environment for a provider CLI, injecting the bootstrap under
56
79
  * the name that CLI actually reads.
@@ -17,6 +17,8 @@ import { existsSync, readFileSync } from "node:fs";
17
17
  import { homedir } from "node:os";
18
18
  import { join } from "node:path";
19
19
 
20
+ import { bootstrapKeyFor } from "./providers.mjs";
21
+
20
22
  /**
21
23
  * Capabilities, per surface.
22
24
  *
@@ -237,10 +239,14 @@ function fromEnvironment(env) {
237
239
  namespace: assertNamespace(namespace),
238
240
  bootstrap: {
239
241
  ...DEFAULTS.bootstrap,
242
+ // Derived from the provider resolved just above, not from Bitwarden's
243
+ // name. Hardcoding it told a Doppler tenant to set BWS_ACCESS_TOKEN_<ns>,
244
+ // which its CLI has never heard of — on the one surface that has no
245
+ // config file to override the guess.
240
246
  key:
241
247
  env.LISA_BOOTSTRAP_KEY ??
242
248
  env.LISA_SECRETS_BOOTSTRAP_KEY ??
243
- `BWS_ACCESS_TOKEN_${namespace}`,
249
+ bootstrapKeyFor(provider, namespace),
244
250
  },
245
251
  };
246
252
  }
@@ -885,6 +885,52 @@ export function pinEnvironment(environmentId, cwd = process.cwd()) {
885
885
  return path;
886
886
  }
887
887
 
888
+ /**
889
+ * The lines an operator puts above the field, for a session with no checkout.
890
+ *
891
+ * Emitted as shell that runs, not as a template with holes: every hole is a
892
+ * hand substitution in a settings box with no review, which is the failure this
893
+ * whole file exists to prevent. So a provider that cannot be bootstrapped by an
894
+ * environment variable gets a sentence explaining that, not an `export` of a
895
+ * placeholder — a line that would be a syntax error if pasted.
896
+ *
897
+ * `LISA_PROVIDER` is exported even though the field defaults it, because the
898
+ * field's default is Bitwarden. A Doppler tenant that omits it gets `bws`
899
+ * installed and its own CLI missing, having configured everything correctly.
900
+ * @param {object} options Resolved identity and display strings.
901
+ * @returns {string[]} Lines to include in the emitted guidance.
902
+ */
903
+ function repoLessExports({ namespace, key, provider, bootstrapKey, tenant }) {
904
+ // Two different reasons the key can be missing, and telling them apart is the
905
+ // whole value of the message. "Nothing was named" is the operator's to fix by
906
+ // re-running; "this provider has no such variable" is not fixable at all and
907
+ // must not read as an omission.
908
+ if (!tenant) {
909
+ return [
910
+ " # Re-run with --tenant=<name> and these are filled in for you.",
911
+ ` export LISA_TENANT=${namespace}`,
912
+ " export <bootstrap variable>='<read from your credential manager>'",
913
+ " export LISA_SECRETS_SURFACE=claude-web",
914
+ ];
915
+ }
916
+ if (!bootstrapKey) {
917
+ return [
918
+ ` # ${provider} has no environment-variable bootstrap, so there is`,
919
+ " # nothing to export for it. Authenticate it the way its own CLI",
920
+ " # expects, then set the three below.",
921
+ ` export LISA_TENANT=${namespace}`,
922
+ ` export LISA_PROVIDER=${provider}`,
923
+ " export LISA_SECRETS_SURFACE=claude-web",
924
+ ];
925
+ }
926
+ return [
927
+ ` export LISA_TENANT=${namespace}`,
928
+ ` export ${key}='<the same value as above>'`,
929
+ ...(provider ? [` export LISA_PROVIDER=${provider}`] : []),
930
+ " export LISA_SECRETS_SURFACE=claude-web",
931
+ ];
932
+ }
933
+
888
934
  /**
889
935
  * Produce the configuration a human pastes to provision a Claude cloud surface.
890
936
  *
@@ -893,11 +939,16 @@ export function pinEnvironment(environmentId, cwd = process.cwd()) {
893
939
  * settings page, no direct URL, and no endpoint. Emit is not a degraded option
894
940
  * here, it is the only one — so the read-back in `verify-remote-env.mjs` is
895
941
  * what makes the result trustworthy, exactly as it would be at any other tier.
896
- * @param {{bootstrapKey: string|null}} options Project details.
942
+ * @param {{bootstrapKey: string|null, tenant?: string|null, provider?: string}} options Project details.
897
943
  * @returns {string} Text to show the operator.
898
944
  */
899
- export function emitClaudeWeb({ bootstrapKey }) {
900
- const key = bootstrapKey ?? "<secrets.bootstrap.key is not configured>";
945
+ export function emitClaudeWeb({
946
+ bootstrapKey,
947
+ tenant = null,
948
+ provider = null,
949
+ }) {
950
+ const key = bootstrapKey ?? "<not resolved>";
951
+ const namespace = tenant ?? "<your namespace>";
901
952
  return [
902
953
  "Provisioning tier: EMIT — and for this surface that is the only tier.",
903
954
  " A Claude cloud environment is account-scoped configuration edited in the",
@@ -924,11 +975,9 @@ export function emitClaudeWeb({ bootstrapKey }) {
924
975
  " while the image is being built, before the environment exists. So a",
925
976
  " session with no checkout has to be told its tenant inside the script",
926
977
  " itself, or the field finds nothing to prepare and exits 0 looking like",
927
- " success. Put these three lines FIRST, then the line after them:",
978
+ " success. Put the lines below FIRST, then the field after them:",
928
979
  "",
929
- " export LISA_TENANT=<your namespace>",
930
- ` export ${key}='<the same value as above>'`,
931
- " export LISA_SECRETS_SURFACE=claude-web",
980
+ ...repoLessExports({ namespace, key, provider, bootstrapKey, tenant }),
932
981
  "",
933
982
  " LISA_SECRETS_SURFACE is set explicitly rather than left to detection:",
934
983
  " detection keys off CLAUDE_CODE_REMOTE, and a surface that does not set",
@@ -1096,6 +1145,66 @@ function readBootstrapKey(cwd = process.cwd()) {
1096
1145
  return JSON.parse(readFileSync(path, "utf8")).secrets?.bootstrap?.key ?? null;
1097
1146
  }
1098
1147
 
1148
+ /**
1149
+ * Work out what to tell the operator to export, for a surface that has no repo.
1150
+ *
1151
+ * Emitting used to read the key out of `.lisa.config.json` in the working
1152
+ * directory, which made the command that configures a REPO-LESS environment
1153
+ * require a repository — so it was run from a checkout that happened to be
1154
+ * nearby, or it printed a placeholder the operator substituted by hand.
1155
+ *
1156
+ * Explicit flags win, then the environment, then a checkout if the caller
1157
+ * happens to be standing in one, then the convention. The provider matters
1158
+ * because it decides the variable's name: `bws` reads `BWS_ACCESS_TOKEN` and
1159
+ * `doppler` reads `DOPPLER_TOKEN`, so a tenant on one told to export the
1160
+ * other's name gets "Missing access token" from a CLI it did configure.
1161
+ * @param {string[]} argv Process arguments.
1162
+ * @param {Record<string, string|undefined>} [env] Environment to read.
1163
+ * @param {string} [cwd] Directory to look for a config in.
1164
+ * @returns {Promise<{tenant: string|null, provider: string, bootstrapKey: string|null}>} Resolved identity.
1165
+ */
1166
+ export async function resolveEmitTarget(
1167
+ argv,
1168
+ env = process.env,
1169
+ cwd = process.cwd()
1170
+ ) {
1171
+ const flag = name =>
1172
+ argv.find(a => a.startsWith(`--${name}=`))?.slice(name.length + 3) ?? null;
1173
+
1174
+ const tenant =
1175
+ flag("tenant") ||
1176
+ (env.LISA_TENANT ?? env.LISA_SECRETS_NAMESPACE ?? "").trim() ||
1177
+ null;
1178
+ const provider =
1179
+ flag("provider") ||
1180
+ (env.LISA_PROVIDER ?? env.LISA_SECRETS_PROVIDER ?? "").trim() ||
1181
+ "bitwarden";
1182
+
1183
+ // Validated before it can reach the output, by the same rule the runtime path
1184
+ // applies. This one becomes `export LISA_TENANT=<value>` in a block an
1185
+ // operator pastes verbatim, so `my tenant` or `has$var` would emit shell that
1186
+ // breaks — or worse, expands — where nothing reviews it. Refusing here costs
1187
+ // a re-run; emitting it costs a container nobody can explain.
1188
+ if (tenant) {
1189
+ const { assertNamespace } = await import(
1190
+ pathToFileURL(siblingScript("lisa-secrets-access", "surfaces.mjs")).href
1191
+ );
1192
+ assertNamespace(tenant);
1193
+ }
1194
+
1195
+ // A configured key outranks the convention: a project may legitimately use a
1196
+ // name that is not derivable, and this command must not tell its operator to
1197
+ // set a different one from the one their sessions actually read.
1198
+ const configured = readBootstrapKey(cwd);
1199
+ if (configured) return { tenant, provider, bootstrapKey: configured };
1200
+ if (!tenant) return { tenant, provider, bootstrapKey: null };
1201
+
1202
+ const { bootstrapKeyFor } = await import(
1203
+ pathToFileURL(siblingScript("lisa-secrets-access", "providers.mjs")).href
1204
+ );
1205
+ return { tenant, provider, bootstrapKey: bootstrapKeyFor(provider, tenant) };
1206
+ }
1207
+
1099
1208
  async function main() {
1100
1209
  // `--print-tools` answers "which CLIs does this secret set imply", reading
1101
1210
  // the notes materialized alongside the values.
@@ -1170,7 +1279,7 @@ async function main() {
1170
1279
  `Emitting is implemented for claude-web, which has no other tier.`
1171
1280
  );
1172
1281
  }
1173
- console.log(emitClaudeWeb({ bootstrapKey: readBootstrapKey() }));
1282
+ console.log(emitClaudeWeb(await resolveEmitTarget(process.argv)));
1174
1283
  return;
1175
1284
  }
1176
1285