Skip to content

feat(compute ssh): --project <id> to target a project without a link - #349

Merged
Fermionic-Lyu merged 1 commit into
mainfrom
feat/compute-ssh-project
Oct 5, 2026
Merged

Fermionic-Lyu merged 1 commit into
mainfrom
feat/compute-ssh-project

Conversation

@Fermionic-Lyu

@Fermionic-Lyu Fermionic-Lyu commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Why

INS-778: the console's SSH instructions don't work as written. The console is moving to a two-step SSH box: a one-time insta compute ssh <service> --setup, then ssh <service>.insta. Whoever copies that setup command is usually not in a directory linked to the project. In an unlinked directory, compute ssh does one of two things:

  • with a TTY, it opens a picker over every project the user can see (50 on my account) and saves the choice as a link in that directory;
  • without a TTY, it fails with several projects and no terminal to pick.

--project <id> lets the console print a command that works from any directory and links nothing.

What

  • insta compute ssh [service] --project <id> uses that project and skips requireProject().
  • The branch defaults to main, because that is what a link records. If it were left unset, assertAliasFree would refuse to set up the same service from a linked directory ('' !== 'main'). -b still overrides it.
  • The flag is checked with !== undefined, so --project "" fails loudly and does not fall back to the picker.
  • Certificate renewal (__ssh-ensure-cert) reads project and service from the alias store, so an alias set up with --project renews from any directory.

Verified

  • npm run typecheck passes; vitest run passes 2022/2022 on Node 22.22.2.
  • Mutation: changing the main default to undefined turns the new test red.
  • Prod, from an empty unlinked directory: insta compute ssh box2 --project <id> --setup (dev build) exited 0 and wrote no .insta/. ssh box2.insta then connected. box2 had already been set up from a linked directory, and the re-setup was not treated as a collision.
  • The installed 0.1.16 says unknown option '--project'. The console change will depend on the release that carries this.

🤖 Generated with Claude Code


Summary by cubic

Adds --project <id> to insta compute ssh so console-printed setup commands work from any directory. Previously an unlinked directory opened a project picker or failed with several projects and no terminal to pick; --project now pins the project and writes no .insta/ link.

The branch defaults to main, what a link records, so a service set up both ways is not refused as a collision, and -b still overrides. --project "" fails loudly instead of falling back to the picker. Aliases set up with --project renew from any directory, since the renewal hook reads project and service from the alias store.

Written for commit a2ac711. Summary will update on new commits.

Review in cubic

The console prints a setup command for a specific service, and the person
copying it is usually not in a directory linked to that project: an
unlinked directory opens a picker over every project (and saves the
choice), or fails with no terminal. --project pins the target and writes
no link. Branch defaults to main, the same value a link records, so a
service set up both ways is not refused as a collision.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@agent-zhang-beihai agent-zhang-beihai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed by Wang Miao

This adds --project <id> to insta compute ssh, so you can mint a certificate and set up an alias for a project without linking the directory first. When the flag is given the branch defaults to main, which matches what project link, auto-resolve and INSTA_PROJECT_ID already record. The code is correct and I'd approve; the one finding below is minor and doesn't block.

--project isn't mirrored in skills/insta/cli-reference.md

minor · defect · conventions · src/index.ts:411

AGENTS.md lists this among its non-negotiables: "Command/flag changes must be mirrored in skills/insta/cli-reference.md (superproject skills/ submodule)". Line 101 of insta/cli-reference.md in InsForge/instacloud-skills still lists compute ssh as [--setup] [-b, --branch <b>] [--json], and none of the open PRs in that repo adds the new flag. It's minor because the same doc says agents can't use compute ssh (it needs an interactive login), so no agent is misled today. Add the flag in a companion skills PR, and note that the branch defaults to main rather than the linked branch.

Evidence

read-the-code: AGENTS.md (Non-negotiables, item 4), src/index.ts:408-414, instacloud-skills:insta/cli-reference.md:101, and the open PR list for InsForge/instacloud-skills. I also checked the 'main' default against src/config.ts:217-224, src/resolve-project.ts:31, src/commands/project.ts:111 and assertAliasFree at src/commands/compute.ts:930-946. I couldn't run the tests here because dependencies aren't installed.

@agent-zhang-beihai agent-zhang-beihai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed by Yang Dong

This lets compute ssh target an explicit project without requiring a repository link, while preserving branch overrides and alias safety. The implementation is sound; I found no findings and approve.

@Fermionic-Lyu

Copy link
Copy Markdown
Member Author

CI test failed on simultaneous stale-lock recovery still admits one holder > never lets two contenders break the same stale lock (two contenders were inside the lock at once). This diff doesn't touch the lock code (breakStaleLock / acquireLockFile); it only changes project resolution in computeSSH and adds tests. The test passed locally on Node 22 and on test-windows in this run, and main's last 8 CI runs are green. Re-running the failed job.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/commands/compute.ts">

<violation number="1" location="src/commands/compute.ts:1957">
P2: `--project` always queries `main`, even when the project’s default branch is `trunk`, so SSH can miss or target the wrong branch’s service. Resolve the project’s default branch when `--branch` is omitted, while preserving `--branch` as the override.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/commands/compute.ts
const api = await (deps.loadApi ?? ApiClient.load)()
const p = await (deps.loadProject ?? requireProject)()
// 'main' is what a link records by default; anything else makes assertAliasFree refuse a setup of the same service from a linked directory.
const p = opts.project !== undefined ? { projectId: opts.project, branch: 'main' } : await (deps.loadProject ?? requireProject)()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: --project always queries main, even when the project’s default branch is trunk, so SSH can miss or target the wrong branch’s service. Resolve the project’s default branch when --branch is omitted, while preserving --branch as the override.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At src/commands/compute.ts, line 1957:

<comment>`--project` always queries `main`, even when the project’s default branch is `trunk`, so SSH can miss or target the wrong branch’s service. Resolve the project’s default branch when `--branch` is omitted, while preserving `--branch` as the override.</comment>

<file context>
@@ -1953,7 +1953,8 @@ export async function computeSSH(serviceName: string | undefined, opts: SSHOpts,
   const api = await (deps.loadApi ?? ApiClient.load)()
-  const p = await (deps.loadProject ?? requireProject)()
+  // 'main' is what a link records by default; anything else makes assertAliasFree refuse a setup of the same service from a linked directory.
+  const p = opts.project !== undefined ? { projectId: opts.project, branch: 'main' } : await (deps.loadProject ?? requireProject)()
   const branch = opts.branch ?? p.branch
   const { services } = await api.request('GET', `/projects/${p.projectId}/services${q(branch)}`)
</file context>
Suggested change
const p = opts.project !== undefined ? { projectId: opts.project, branch: 'main' } : await (deps.loadProject ?? requireProject)()
const p = opts.project !== undefined
? {
projectId: opts.project,
branch: opts.branch ?? (await api.request<{ branches?: Array<{ name: string; is_default?: boolean }> }>('GET', `/projects/${opts.project}`)).branches?.find((b) => b.is_default)?.name ?? 'main',
}
: await (deps.loadProject ?? requireProject)()

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declining: there is no project whose default branch isn't main. The platform hard-codes it when it creates a project: src/provisioning/service.ts:55 in insta-platform @ 4a5efe3a runs BranchesRepo.create({ projectId, name: 'main', isDefault: true, ... }). Every CLI link writer records main too (project.ts link, resolve-project.ts auto-resolve, config.ts INSTA_PROJECT_ID). Resolving the default branch over the network would add a request to get a value that is always the same, and --branch already covers any other branch.

@Fermionic-Lyu

Copy link
Copy Markdown
Member Author

Wang Miao's cli-reference.md finding is handled in InsForge/instacloud-skills#160, which adds the flag and notes that the branch defaults to main. The cubic finding about trunk is declined in its thread: the platform always names the default branch main. CI is green on a2ac711 after re-running the flaky lock test.

@jwfing jwfing left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - approved.

@Fermionic-Lyu
Fermionic-Lyu merged commit 715a2d1 into main Oct 5, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants