@codyswann/lisa 2.321.0 → 2.321.2
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.
- package/dist/core/upstream-evidence-manifest.js +5 -5
- package/expo/package-lisa/package.lisa.json +2 -2
- package/package.json +3 -3
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/SKILL.md +2 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/assets/setup.sh +10 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +42 -8
- package/plugins/lisa/skills/lisa-setup-remote-env/SKILL.md +2 -0
- package/plugins/lisa/skills/lisa-setup-remote-env/assets/setup.sh +10 -0
- package/plugins/lisa/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +42 -8
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/SKILL.md +2 -0
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/assets/setup.sh +10 -0
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +42 -8
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/SKILL.md +2 -0
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/assets/setup.sh +10 -0
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +42 -8
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/SKILL.md +2 -0
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/assets/setup.sh +10 -0
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +42 -8
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/skills/lisa-setup-remote-env/SKILL.md +2 -0
- package/plugins/src/base/skills/lisa-setup-remote-env/assets/setup.sh +10 -0
- package/plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +42 -8
- package/typescript/package-lisa/package.lisa.json +2 -2
|
@@ -93,7 +93,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
|
|
|
93
93
|
"expo/github-rulesets/playwright.json": "b57ccd12f768a1466a9681528858e59764bd0efedcbcb3a96c2fb40719bbd579",
|
|
94
94
|
"expo/merge/.claude/settings.json": "e97b33d7ad86b71abba94ab957d725e34c3cafca455e92fba0b29ebabc3b73d1",
|
|
95
95
|
"expo/merge/.oxlintrc.json": "2a0ea2191abd5b377aed4b525a4a97d3eefb1d9e41c845c02ee0daac75df6b1f",
|
|
96
|
-
"expo/package-lisa/package.lisa.json": "
|
|
96
|
+
"expo/package-lisa/package.lisa.json": "c0d30ba53a179acb8720c4443b5f5fd6df092f735b9e3fbcea34f6b4995def0f",
|
|
97
97
|
"harper-fabric/copy-contents/.prettierignore": "478c782f4c5611187e21584dfd5522e37fc636c5eb03394fea3db45321c6712c",
|
|
98
98
|
"harper-fabric/copy-contents/gitignore": "d091c40fd0ea3068491f1be0d6510090ae872ca95d0d058ef4595d6492d13897",
|
|
99
99
|
"harper-fabric/copy-overwrite/.github/dependabot.yml": "e28fde0d906478b3fb7d6b7fc16f7fc5a4a0a20d8160f547f2b4be97c90578b7",
|
|
@@ -559,10 +559,10 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
|
|
|
559
559
|
"plugins/src/base/skills/lisa-setup-linear/SKILL.md": "ec76f832a6df6f58b163f7f5ba6826ed2fcbddc91e44a8372e874858e4d0c518",
|
|
560
560
|
"plugins/src/base/skills/lisa-setup-notion/SKILL.md": "f5a1e9290789fd1c33675168d30461fb24a11c98a433ef777c1f536bc2f905ef",
|
|
561
561
|
"plugins/src/base/skills/lisa-setup-remote-aws/SKILL.md": "80fbf157f9c562c033886c25a99b37356602edd9e61cd2d492f339769ddcf97e",
|
|
562
|
-
"plugins/src/base/skills/lisa-setup-remote-env/SKILL.md": "
|
|
562
|
+
"plugins/src/base/skills/lisa-setup-remote-env/SKILL.md": "313d1b96500950b566a3e22bc1620662a76635c89c6c90c2648d48e0497574b7",
|
|
563
563
|
"plugins/src/base/skills/lisa-setup-remote-env/assets/session-start.sh": "6e3871ec2f8d56b8ebb85376ebdd3956f3ed8fa4f7b278c2ed90ca9b8845897c",
|
|
564
|
-
"plugins/src/base/skills/lisa-setup-remote-env/assets/setup.sh": "
|
|
565
|
-
"plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs": "
|
|
564
|
+
"plugins/src/base/skills/lisa-setup-remote-env/assets/setup.sh": "f1b492196f41adcceb1c2a2ada048355e7f36735de3be0dfe028e472b452f28c",
|
|
565
|
+
"plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs": "0ac27775b2a11cc7ab6368aba4df7466cbf8cf57fd5470a807e24547b36cc94f",
|
|
566
566
|
"plugins/src/base/skills/lisa-setup-remote-env/scripts/toolchain.mjs": "ff66d33ba41a068d09be18f81ac68988238c2afa1d4e3733ae906b73eea74324",
|
|
567
567
|
"plugins/src/base/skills/lisa-setup-remote-env/scripts/verify-remote-env.mjs": "82bc2a27a0a5afb2ff413a88365c619fd7f0eaada5de3ccabf2000938f0607a4",
|
|
568
568
|
"plugins/src/base/skills/lisa-setup-sonar/SKILL.md": "53fbd8acce4b5e47e88195a7b90d5be424fa6ef7ad872f52c50467c690664c3b",
|
|
@@ -1077,7 +1077,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
|
|
|
1077
1077
|
"typescript/github-rulesets/quality-checks.json": "d92599b203071b99b8fac1422b8493d2546138961ef04ba98176bc400af60945",
|
|
1078
1078
|
"typescript/merge/.claude/settings.json": "834e6456cae81f45073bbbb08bf731fef043efb30cae2658cb4a59f17e66d165",
|
|
1079
1079
|
"typescript/merge/.oxlintrc.json": "4debc093acfd263eb81ae15894073ebf098513204f45f40b83fb8fa5353fa1f8",
|
|
1080
|
-
"typescript/package-lisa/package.lisa.json": "
|
|
1080
|
+
"typescript/package-lisa/package.lisa.json": "5d66792e54b1ed0ca1f2103e504f77a6afb8187660404ddba24936b049568934",
|
|
1081
1081
|
"ui/README.md": "deeb35e767ea5dd2883268835ea3ad21cbad9fa63ec8d8ff5e200f0e2a7d2751",
|
|
1082
1082
|
"ui/index.html": "400088617ed6f16b4e52da5bfa81242d75cb09bc3ad6929eadb9f06e5365b4b6",
|
|
1083
1083
|
});
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
},
|
|
99
99
|
"resolutions": {
|
|
100
100
|
"@isaacs/brace-expansion": "^5.0.1",
|
|
101
|
-
"brace-expansion": ">=5.0.
|
|
101
|
+
"brace-expansion": ">=5.0.9",
|
|
102
102
|
"eslint-plugin-react-hooks": "^7.0.0",
|
|
103
103
|
"fast-xml-parser": "^5.10.1",
|
|
104
104
|
"tar": ">=7.5.19",
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
},
|
|
107
107
|
"overrides": {
|
|
108
108
|
"@isaacs/brace-expansion": "^5.0.1",
|
|
109
|
-
"brace-expansion": ">=5.0.
|
|
109
|
+
"brace-expansion": ">=5.0.9",
|
|
110
110
|
"eslint-plugin-react-hooks": "^7.0.0",
|
|
111
111
|
"fast-xml-parser": "^5.10.1",
|
|
112
112
|
"zod-validation-error": "^4.0.0",
|
package/package.json
CHANGED
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"postcss": ">=8.5.18",
|
|
98
98
|
"undici": "^6.27.0",
|
|
99
99
|
"form-data": ">=4.0.6",
|
|
100
|
-
"brace-expansion": ">=5.0.
|
|
100
|
+
"brace-expansion": ">=5.0.9"
|
|
101
101
|
},
|
|
102
102
|
"overrides": {
|
|
103
103
|
"@isaacs/brace-expansion": "^5.0.1",
|
|
@@ -112,10 +112,10 @@
|
|
|
112
112
|
"postcss": ">=8.5.18",
|
|
113
113
|
"undici": "^6.27.0",
|
|
114
114
|
"form-data": ">=4.0.6",
|
|
115
|
-
"brace-expansion": ">=5.0.
|
|
115
|
+
"brace-expansion": ">=5.0.9"
|
|
116
116
|
},
|
|
117
117
|
"name": "@codyswann/lisa",
|
|
118
|
-
"version": "2.321.
|
|
118
|
+
"version": "2.321.2",
|
|
119
119
|
"description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
|
|
120
120
|
"main": "dist/index.js",
|
|
121
121
|
"exports": {
|
|
@@ -161,6 +161,8 @@ It reads the project's own install command from its lockfile and the bootstrap n
|
|
|
161
161
|
|
|
162
162
|
- **`gh` is not pre-installed.** If the project's flows shell out to it, add it to `remoteEnv.tools.install`, pinned and checksummed like anything else.
|
|
163
163
|
- **A proxied credential reads as the literal string `proxy-injected`.** Tools that authenticate through the GitHub proxy work; a script that reads the variable directly gets the placeholder. The read-back asserts this rather than leaving it to be discovered against a live service.
|
|
164
|
+
- **The setup field runs from `$HOME`, not from the checkout.** The emitted setup command starts with `cd <repo-name>` on purpose; without it the package install runs one directory above the clone and cannot find `package.json`.
|
|
165
|
+
- **Trusted network access is not enough for provider CLIs.** Use Custom and include package registries, GitHub, cloud SDK hosts, and the bootstrap credential manager API.
|
|
164
166
|
|
|
165
167
|
### One environment per project, pinned locally
|
|
166
168
|
|
|
@@ -13,6 +13,16 @@
|
|
|
13
13
|
# and emphatically not in a vendor settings field.
|
|
14
14
|
set -euo pipefail
|
|
15
15
|
|
|
16
|
+
# Claude Code web runs the environment setup field from $HOME, while the
|
|
17
|
+
# checkout lives at $HOME/<repo>. If this installed copy is invoked by absolute
|
|
18
|
+
# path, move back to the repository root before resolving project-local files.
|
|
19
|
+
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
20
|
+
case "$script_dir" in
|
|
21
|
+
*/scripts/lisa-remote-env)
|
|
22
|
+
cd "$script_dir/../.."
|
|
23
|
+
;;
|
|
24
|
+
esac
|
|
25
|
+
|
|
16
26
|
# Node is the one thing that cannot be installed by the installer, since the
|
|
17
27
|
# installer is written in it. Fail with an actionable message rather than a
|
|
18
28
|
# "command not found" forty lines deep.
|
package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs
CHANGED
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
rmSync,
|
|
38
38
|
writeFileSync,
|
|
39
39
|
} from "node:fs";
|
|
40
|
-
import { dirname, join, resolve } from "node:path";
|
|
40
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
41
41
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
42
42
|
|
|
43
43
|
import { assertPinned, extractVersion, planToolchain } from "./toolchain.mjs";
|
|
@@ -337,11 +337,12 @@ export function pinEnvironment(environmentId, cwd = process.cwd()) {
|
|
|
337
337
|
* settings page, no direct URL, and no endpoint. Emit is not a degraded option
|
|
338
338
|
* here, it is the only one — so the read-back in `verify-remote-env.mjs` is
|
|
339
339
|
* what makes the result trustworthy, exactly as it would be at any other tier.
|
|
340
|
-
* @param {{bootstrapKey: string|null, install: string}} options Project details.
|
|
340
|
+
* @param {{bootstrapKey: string|null, install: string, repoDir?: string}} options Project details.
|
|
341
341
|
* @returns {string} Text to show the operator.
|
|
342
342
|
*/
|
|
343
|
-
export function emitClaudeWeb({ bootstrapKey, install }) {
|
|
343
|
+
export function emitClaudeWeb({ bootstrapKey, install, repoDir = "lisa" }) {
|
|
344
344
|
const key = bootstrapKey ?? "<secrets.bootstrap.key is not configured>";
|
|
345
|
+
const setup = `cd ${shellQuote(repoDir)} && ${install} && bash scripts/lisa-remote-env/setup.sh`;
|
|
345
346
|
return [
|
|
346
347
|
"Provisioning tier: EMIT — and for this surface that is the only tier.",
|
|
347
348
|
" A Claude cloud environment is account-scoped configuration edited in the",
|
|
@@ -350,7 +351,8 @@ export function emitClaudeWeb({ bootstrapKey, install }) {
|
|
|
350
351
|
"",
|
|
351
352
|
"Paste into the environment dialog",
|
|
352
353
|
"---------------------------------",
|
|
353
|
-
" Network access:
|
|
354
|
+
" Network access: Custom plus your package registries, GitHub, cloud SDK",
|
|
355
|
+
" hosts, and the bootstrap credential manager API",
|
|
354
356
|
"",
|
|
355
357
|
" Environment variables:",
|
|
356
358
|
` ${key}=<read this from your credential manager>`,
|
|
@@ -362,11 +364,13 @@ export function emitClaudeWeb({ bootstrapKey, install }) {
|
|
|
362
364
|
" is why exactly one value needs to live here.",
|
|
363
365
|
"",
|
|
364
366
|
" Setup script:",
|
|
365
|
-
` ${
|
|
367
|
+
` ${setup}`,
|
|
366
368
|
"",
|
|
367
|
-
|
|
368
|
-
"
|
|
369
|
-
"
|
|
369
|
+
` Claude runs this field from $HOME, while the checkout is $HOME/${repoDir}.`,
|
|
370
|
+
" The `cd` must come first, and the install must run before the setup",
|
|
371
|
+
" script. On a fresh container node_modules is the only copy of the Lisa",
|
|
372
|
+
" skills present, because Claude receives them as an installed plugin",
|
|
373
|
+
" rather than as part of the clone.",
|
|
370
374
|
"",
|
|
371
375
|
"Commit to the repository",
|
|
372
376
|
"------------------------",
|
|
@@ -467,6 +471,35 @@ export function detectInstallCommand(cwd = process.cwd()) {
|
|
|
467
471
|
return "<your install command>";
|
|
468
472
|
}
|
|
469
473
|
|
|
474
|
+
/**
|
|
475
|
+
* Name the directory Claude creates under $HOME when it clones this repository.
|
|
476
|
+
*
|
|
477
|
+
* Claude cloud runs the environment setup field from $HOME, not from the
|
|
478
|
+
* checkout. The setup line therefore has to `cd` into the clone before running
|
|
479
|
+
* the project install. Prefer the configured GitHub repo name because it is the
|
|
480
|
+
* thing Claude clones; fall back to the current directory for non-GitHub tests
|
|
481
|
+
* and local dry runs.
|
|
482
|
+
* @param {string} [cwd] Repository root.
|
|
483
|
+
* @returns {string} Directory name to place after `cd`.
|
|
484
|
+
*/
|
|
485
|
+
export function detectRepositoryDirectory(cwd = process.cwd()) {
|
|
486
|
+
const path = join(cwd, ".lisa.config.json");
|
|
487
|
+
if (existsSync(path)) {
|
|
488
|
+
const repo = JSON.parse(readFileSync(path, "utf8")).github?.repo;
|
|
489
|
+
if (repo && !repo.includes("/") && !repo.includes("\0")) return repo;
|
|
490
|
+
}
|
|
491
|
+
return basename(cwd);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Quote a value for POSIX shell usage.
|
|
496
|
+
* @param {string} value Raw value.
|
|
497
|
+
* @returns {string} Single-quoted shell literal.
|
|
498
|
+
*/
|
|
499
|
+
function shellQuote(value) {
|
|
500
|
+
return "'" + String(value).replaceAll("'", "'\\''") + "'";
|
|
501
|
+
}
|
|
502
|
+
|
|
470
503
|
/**
|
|
471
504
|
* Read the bootstrap key name, which is the one value the operator must paste.
|
|
472
505
|
* @param {string} [cwd] Repository root.
|
|
@@ -519,6 +552,7 @@ async function main() {
|
|
|
519
552
|
emitClaudeWeb({
|
|
520
553
|
bootstrapKey: readBootstrapKey(),
|
|
521
554
|
install: detectInstallCommand(),
|
|
555
|
+
repoDir: detectRepositoryDirectory(),
|
|
522
556
|
})
|
|
523
557
|
);
|
|
524
558
|
return;
|
|
@@ -161,6 +161,8 @@ It reads the project's own install command from its lockfile and the bootstrap n
|
|
|
161
161
|
|
|
162
162
|
- **`gh` is not pre-installed.** If the project's flows shell out to it, add it to `remoteEnv.tools.install`, pinned and checksummed like anything else.
|
|
163
163
|
- **A proxied credential reads as the literal string `proxy-injected`.** Tools that authenticate through the GitHub proxy work; a script that reads the variable directly gets the placeholder. The read-back asserts this rather than leaving it to be discovered against a live service.
|
|
164
|
+
- **The setup field runs from `$HOME`, not from the checkout.** The emitted setup command starts with `cd <repo-name>` on purpose; without it the package install runs one directory above the clone and cannot find `package.json`.
|
|
165
|
+
- **Trusted network access is not enough for provider CLIs.** Use Custom and include package registries, GitHub, cloud SDK hosts, and the bootstrap credential manager API.
|
|
164
166
|
|
|
165
167
|
### One environment per project, pinned locally
|
|
166
168
|
|
|
@@ -13,6 +13,16 @@
|
|
|
13
13
|
# and emphatically not in a vendor settings field.
|
|
14
14
|
set -euo pipefail
|
|
15
15
|
|
|
16
|
+
# Claude Code web runs the environment setup field from $HOME, while the
|
|
17
|
+
# checkout lives at $HOME/<repo>. If this installed copy is invoked by absolute
|
|
18
|
+
# path, move back to the repository root before resolving project-local files.
|
|
19
|
+
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
20
|
+
case "$script_dir" in
|
|
21
|
+
*/scripts/lisa-remote-env)
|
|
22
|
+
cd "$script_dir/../.."
|
|
23
|
+
;;
|
|
24
|
+
esac
|
|
25
|
+
|
|
16
26
|
# Node is the one thing that cannot be installed by the installer, since the
|
|
17
27
|
# installer is written in it. Fail with an actionable message rather than a
|
|
18
28
|
# "command not found" forty lines deep.
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
rmSync,
|
|
38
38
|
writeFileSync,
|
|
39
39
|
} from "node:fs";
|
|
40
|
-
import { dirname, join, resolve } from "node:path";
|
|
40
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
41
41
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
42
42
|
|
|
43
43
|
import { assertPinned, extractVersion, planToolchain } from "./toolchain.mjs";
|
|
@@ -337,11 +337,12 @@ export function pinEnvironment(environmentId, cwd = process.cwd()) {
|
|
|
337
337
|
* settings page, no direct URL, and no endpoint. Emit is not a degraded option
|
|
338
338
|
* here, it is the only one — so the read-back in `verify-remote-env.mjs` is
|
|
339
339
|
* what makes the result trustworthy, exactly as it would be at any other tier.
|
|
340
|
-
* @param {{bootstrapKey: string|null, install: string}} options Project details.
|
|
340
|
+
* @param {{bootstrapKey: string|null, install: string, repoDir?: string}} options Project details.
|
|
341
341
|
* @returns {string} Text to show the operator.
|
|
342
342
|
*/
|
|
343
|
-
export function emitClaudeWeb({ bootstrapKey, install }) {
|
|
343
|
+
export function emitClaudeWeb({ bootstrapKey, install, repoDir = "lisa" }) {
|
|
344
344
|
const key = bootstrapKey ?? "<secrets.bootstrap.key is not configured>";
|
|
345
|
+
const setup = `cd ${shellQuote(repoDir)} && ${install} && bash scripts/lisa-remote-env/setup.sh`;
|
|
345
346
|
return [
|
|
346
347
|
"Provisioning tier: EMIT — and for this surface that is the only tier.",
|
|
347
348
|
" A Claude cloud environment is account-scoped configuration edited in the",
|
|
@@ -350,7 +351,8 @@ export function emitClaudeWeb({ bootstrapKey, install }) {
|
|
|
350
351
|
"",
|
|
351
352
|
"Paste into the environment dialog",
|
|
352
353
|
"---------------------------------",
|
|
353
|
-
" Network access:
|
|
354
|
+
" Network access: Custom plus your package registries, GitHub, cloud SDK",
|
|
355
|
+
" hosts, and the bootstrap credential manager API",
|
|
354
356
|
"",
|
|
355
357
|
" Environment variables:",
|
|
356
358
|
` ${key}=<read this from your credential manager>`,
|
|
@@ -362,11 +364,13 @@ export function emitClaudeWeb({ bootstrapKey, install }) {
|
|
|
362
364
|
" is why exactly one value needs to live here.",
|
|
363
365
|
"",
|
|
364
366
|
" Setup script:",
|
|
365
|
-
` ${
|
|
367
|
+
` ${setup}`,
|
|
366
368
|
"",
|
|
367
|
-
|
|
368
|
-
"
|
|
369
|
-
"
|
|
369
|
+
` Claude runs this field from $HOME, while the checkout is $HOME/${repoDir}.`,
|
|
370
|
+
" The `cd` must come first, and the install must run before the setup",
|
|
371
|
+
" script. On a fresh container node_modules is the only copy of the Lisa",
|
|
372
|
+
" skills present, because Claude receives them as an installed plugin",
|
|
373
|
+
" rather than as part of the clone.",
|
|
370
374
|
"",
|
|
371
375
|
"Commit to the repository",
|
|
372
376
|
"------------------------",
|
|
@@ -467,6 +471,35 @@ export function detectInstallCommand(cwd = process.cwd()) {
|
|
|
467
471
|
return "<your install command>";
|
|
468
472
|
}
|
|
469
473
|
|
|
474
|
+
/**
|
|
475
|
+
* Name the directory Claude creates under $HOME when it clones this repository.
|
|
476
|
+
*
|
|
477
|
+
* Claude cloud runs the environment setup field from $HOME, not from the
|
|
478
|
+
* checkout. The setup line therefore has to `cd` into the clone before running
|
|
479
|
+
* the project install. Prefer the configured GitHub repo name because it is the
|
|
480
|
+
* thing Claude clones; fall back to the current directory for non-GitHub tests
|
|
481
|
+
* and local dry runs.
|
|
482
|
+
* @param {string} [cwd] Repository root.
|
|
483
|
+
* @returns {string} Directory name to place after `cd`.
|
|
484
|
+
*/
|
|
485
|
+
export function detectRepositoryDirectory(cwd = process.cwd()) {
|
|
486
|
+
const path = join(cwd, ".lisa.config.json");
|
|
487
|
+
if (existsSync(path)) {
|
|
488
|
+
const repo = JSON.parse(readFileSync(path, "utf8")).github?.repo;
|
|
489
|
+
if (repo && !repo.includes("/") && !repo.includes("\0")) return repo;
|
|
490
|
+
}
|
|
491
|
+
return basename(cwd);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Quote a value for POSIX shell usage.
|
|
496
|
+
* @param {string} value Raw value.
|
|
497
|
+
* @returns {string} Single-quoted shell literal.
|
|
498
|
+
*/
|
|
499
|
+
function shellQuote(value) {
|
|
500
|
+
return "'" + String(value).replaceAll("'", "'\\''") + "'";
|
|
501
|
+
}
|
|
502
|
+
|
|
470
503
|
/**
|
|
471
504
|
* Read the bootstrap key name, which is the one value the operator must paste.
|
|
472
505
|
* @param {string} [cwd] Repository root.
|
|
@@ -519,6 +552,7 @@ async function main() {
|
|
|
519
552
|
emitClaudeWeb({
|
|
520
553
|
bootstrapKey: readBootstrapKey(),
|
|
521
554
|
install: detectInstallCommand(),
|
|
555
|
+
repoDir: detectRepositoryDirectory(),
|
|
522
556
|
})
|
|
523
557
|
);
|
|
524
558
|
return;
|
|
@@ -161,6 +161,8 @@ It reads the project's own install command from its lockfile and the bootstrap n
|
|
|
161
161
|
|
|
162
162
|
- **`gh` is not pre-installed.** If the project's flows shell out to it, add it to `remoteEnv.tools.install`, pinned and checksummed like anything else.
|
|
163
163
|
- **A proxied credential reads as the literal string `proxy-injected`.** Tools that authenticate through the GitHub proxy work; a script that reads the variable directly gets the placeholder. The read-back asserts this rather than leaving it to be discovered against a live service.
|
|
164
|
+
- **The setup field runs from `$HOME`, not from the checkout.** The emitted setup command starts with `cd <repo-name>` on purpose; without it the package install runs one directory above the clone and cannot find `package.json`.
|
|
165
|
+
- **Trusted network access is not enough for provider CLIs.** Use Custom and include package registries, GitHub, cloud SDK hosts, and the bootstrap credential manager API.
|
|
164
166
|
|
|
165
167
|
### One environment per project, pinned locally
|
|
166
168
|
|
|
@@ -13,6 +13,16 @@
|
|
|
13
13
|
# and emphatically not in a vendor settings field.
|
|
14
14
|
set -euo pipefail
|
|
15
15
|
|
|
16
|
+
# Claude Code web runs the environment setup field from $HOME, while the
|
|
17
|
+
# checkout lives at $HOME/<repo>. If this installed copy is invoked by absolute
|
|
18
|
+
# path, move back to the repository root before resolving project-local files.
|
|
19
|
+
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
20
|
+
case "$script_dir" in
|
|
21
|
+
*/scripts/lisa-remote-env)
|
|
22
|
+
cd "$script_dir/../.."
|
|
23
|
+
;;
|
|
24
|
+
esac
|
|
25
|
+
|
|
16
26
|
# Node is the one thing that cannot be installed by the installer, since the
|
|
17
27
|
# installer is written in it. Fail with an actionable message rather than a
|
|
18
28
|
# "command not found" forty lines deep.
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
rmSync,
|
|
38
38
|
writeFileSync,
|
|
39
39
|
} from "node:fs";
|
|
40
|
-
import { dirname, join, resolve } from "node:path";
|
|
40
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
41
41
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
42
42
|
|
|
43
43
|
import { assertPinned, extractVersion, planToolchain } from "./toolchain.mjs";
|
|
@@ -337,11 +337,12 @@ export function pinEnvironment(environmentId, cwd = process.cwd()) {
|
|
|
337
337
|
* settings page, no direct URL, and no endpoint. Emit is not a degraded option
|
|
338
338
|
* here, it is the only one — so the read-back in `verify-remote-env.mjs` is
|
|
339
339
|
* what makes the result trustworthy, exactly as it would be at any other tier.
|
|
340
|
-
* @param {{bootstrapKey: string|null, install: string}} options Project details.
|
|
340
|
+
* @param {{bootstrapKey: string|null, install: string, repoDir?: string}} options Project details.
|
|
341
341
|
* @returns {string} Text to show the operator.
|
|
342
342
|
*/
|
|
343
|
-
export function emitClaudeWeb({ bootstrapKey, install }) {
|
|
343
|
+
export function emitClaudeWeb({ bootstrapKey, install, repoDir = "lisa" }) {
|
|
344
344
|
const key = bootstrapKey ?? "<secrets.bootstrap.key is not configured>";
|
|
345
|
+
const setup = `cd ${shellQuote(repoDir)} && ${install} && bash scripts/lisa-remote-env/setup.sh`;
|
|
345
346
|
return [
|
|
346
347
|
"Provisioning tier: EMIT — and for this surface that is the only tier.",
|
|
347
348
|
" A Claude cloud environment is account-scoped configuration edited in the",
|
|
@@ -350,7 +351,8 @@ export function emitClaudeWeb({ bootstrapKey, install }) {
|
|
|
350
351
|
"",
|
|
351
352
|
"Paste into the environment dialog",
|
|
352
353
|
"---------------------------------",
|
|
353
|
-
" Network access:
|
|
354
|
+
" Network access: Custom plus your package registries, GitHub, cloud SDK",
|
|
355
|
+
" hosts, and the bootstrap credential manager API",
|
|
354
356
|
"",
|
|
355
357
|
" Environment variables:",
|
|
356
358
|
` ${key}=<read this from your credential manager>`,
|
|
@@ -362,11 +364,13 @@ export function emitClaudeWeb({ bootstrapKey, install }) {
|
|
|
362
364
|
" is why exactly one value needs to live here.",
|
|
363
365
|
"",
|
|
364
366
|
" Setup script:",
|
|
365
|
-
` ${
|
|
367
|
+
` ${setup}`,
|
|
366
368
|
"",
|
|
367
|
-
|
|
368
|
-
"
|
|
369
|
-
"
|
|
369
|
+
` Claude runs this field from $HOME, while the checkout is $HOME/${repoDir}.`,
|
|
370
|
+
" The `cd` must come first, and the install must run before the setup",
|
|
371
|
+
" script. On a fresh container node_modules is the only copy of the Lisa",
|
|
372
|
+
" skills present, because Claude receives them as an installed plugin",
|
|
373
|
+
" rather than as part of the clone.",
|
|
370
374
|
"",
|
|
371
375
|
"Commit to the repository",
|
|
372
376
|
"------------------------",
|
|
@@ -467,6 +471,35 @@ export function detectInstallCommand(cwd = process.cwd()) {
|
|
|
467
471
|
return "<your install command>";
|
|
468
472
|
}
|
|
469
473
|
|
|
474
|
+
/**
|
|
475
|
+
* Name the directory Claude creates under $HOME when it clones this repository.
|
|
476
|
+
*
|
|
477
|
+
* Claude cloud runs the environment setup field from $HOME, not from the
|
|
478
|
+
* checkout. The setup line therefore has to `cd` into the clone before running
|
|
479
|
+
* the project install. Prefer the configured GitHub repo name because it is the
|
|
480
|
+
* thing Claude clones; fall back to the current directory for non-GitHub tests
|
|
481
|
+
* and local dry runs.
|
|
482
|
+
* @param {string} [cwd] Repository root.
|
|
483
|
+
* @returns {string} Directory name to place after `cd`.
|
|
484
|
+
*/
|
|
485
|
+
export function detectRepositoryDirectory(cwd = process.cwd()) {
|
|
486
|
+
const path = join(cwd, ".lisa.config.json");
|
|
487
|
+
if (existsSync(path)) {
|
|
488
|
+
const repo = JSON.parse(readFileSync(path, "utf8")).github?.repo;
|
|
489
|
+
if (repo && !repo.includes("/") && !repo.includes("\0")) return repo;
|
|
490
|
+
}
|
|
491
|
+
return basename(cwd);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Quote a value for POSIX shell usage.
|
|
496
|
+
* @param {string} value Raw value.
|
|
497
|
+
* @returns {string} Single-quoted shell literal.
|
|
498
|
+
*/
|
|
499
|
+
function shellQuote(value) {
|
|
500
|
+
return "'" + String(value).replaceAll("'", "'\\''") + "'";
|
|
501
|
+
}
|
|
502
|
+
|
|
470
503
|
/**
|
|
471
504
|
* Read the bootstrap key name, which is the one value the operator must paste.
|
|
472
505
|
* @param {string} [cwd] Repository root.
|
|
@@ -519,6 +552,7 @@ async function main() {
|
|
|
519
552
|
emitClaudeWeb({
|
|
520
553
|
bootstrapKey: readBootstrapKey(),
|
|
521
554
|
install: detectInstallCommand(),
|
|
555
|
+
repoDir: detectRepositoryDirectory(),
|
|
522
556
|
})
|
|
523
557
|
);
|
|
524
558
|
return;
|
|
@@ -161,6 +161,8 @@ It reads the project's own install command from its lockfile and the bootstrap n
|
|
|
161
161
|
|
|
162
162
|
- **`gh` is not pre-installed.** If the project's flows shell out to it, add it to `remoteEnv.tools.install`, pinned and checksummed like anything else.
|
|
163
163
|
- **A proxied credential reads as the literal string `proxy-injected`.** Tools that authenticate through the GitHub proxy work; a script that reads the variable directly gets the placeholder. The read-back asserts this rather than leaving it to be discovered against a live service.
|
|
164
|
+
- **The setup field runs from `$HOME`, not from the checkout.** The emitted setup command starts with `cd <repo-name>` on purpose; without it the package install runs one directory above the clone and cannot find `package.json`.
|
|
165
|
+
- **Trusted network access is not enough for provider CLIs.** Use Custom and include package registries, GitHub, cloud SDK hosts, and the bootstrap credential manager API.
|
|
164
166
|
|
|
165
167
|
### One environment per project, pinned locally
|
|
166
168
|
|
|
@@ -13,6 +13,16 @@
|
|
|
13
13
|
# and emphatically not in a vendor settings field.
|
|
14
14
|
set -euo pipefail
|
|
15
15
|
|
|
16
|
+
# Claude Code web runs the environment setup field from $HOME, while the
|
|
17
|
+
# checkout lives at $HOME/<repo>. If this installed copy is invoked by absolute
|
|
18
|
+
# path, move back to the repository root before resolving project-local files.
|
|
19
|
+
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
20
|
+
case "$script_dir" in
|
|
21
|
+
*/scripts/lisa-remote-env)
|
|
22
|
+
cd "$script_dir/../.."
|
|
23
|
+
;;
|
|
24
|
+
esac
|
|
25
|
+
|
|
16
26
|
# Node is the one thing that cannot be installed by the installer, since the
|
|
17
27
|
# installer is written in it. Fail with an actionable message rather than a
|
|
18
28
|
# "command not found" forty lines deep.
|