Skip to content

Provide an explicit SDK API for built-in shell tool startup env/scripts #1911

Description

@anthonykim1

I am trying to make Python environment auto-activation work when VS Code (with Agent Host Copilot) runs commands through the SDK-owned built-in shell tool.

Relevant context: microsoft/vscode#323164

VS Code Python environment extension has shellStartup activation writes shell-specific activation commands into env vars such as:

VSCODE_PYTHON_BASH_ACTIVATE
VSCODE_PYTHON_ZSH_ACTIVATE
VSCODE_PYTHON_PWSH_ACTIVATE

VS Code terminal shell integration/profile startup then evaluates those variables during shell startup. But when Agent Host Copilot uses the SDK-owned built-in shell tool, we do not run the shell integration script from VS Code upon launch of Copilot terminal.

  • That means agent-run Python commands/scripts can run in the wrong Python environment unless the SDK host has a supported way to provide equivalent shell startup material.

Some relevant pre-existing things:
The SDK/runtime seems to expose part of shell startup configuration through session RPC:

// node_modules/@github/copilot-sdk/dist/generated/rpc.d.ts

export interface SessionUpdateOptionsParams {
  /** Shell init profile (`None` or `NonInteractive`). */
  shellInitProfile?: string;

  /** Per-shell process flags (e.g., `pwsh` arguments). */
  shellProcessFlags?: string[];
}

Given that shape, I expected an SDK host to have some supported way to configure shell startup material for the built-in shell tool:

await session.rpc.options.update({
  shellInitProfile: "non-interactive",
  // expected: some supported way to provide startup env/script material
  // for built-in shell tool child processes
});

Actual behavior seems to be that shellInitProfile only selects preset behavior. It is not a path to an rc file, profile file, or custom startup script.

For bash, the closest workaround(?) may be to set BASH_ENV on the SDK runtime process and select the non-interactive shell init profile:

const client = new CopilotClient({
  env: {
    ...process.env,
    BASH_ENV: "/path/to/generated-python-activation.sh",
  },
});

const session = await client.createSession({ /* ... */ });

await session.rpc.options.update({
  shellInitProfile: "non-interactive",
});

That workaround is not ideal as the only supported SDK shape for VS Code's Copilot integration:

  1. BASH_ENV is bash-specific (we need ways to source zshrc, bashrc, powershell profile, custom integration scripts, etc)
  2. There is no obvious SDK API to provide a custom init script per shell.
  3. There is no obvious SDK API to say "source this generated startup script before built-in shell tool commands."

Ask/Plans forward(More than happy to put up a PR for this):

I am not asking for the built-in shell tool to automatically source user rc/profile files by default:

  • Rather, We should have an explicit, opt-in SDK API where the host can provide shell startup material for SDK-owned shell tools, with clear scoping semantics.

For example, this could be runtime/client-scoped if that matches the SDK ownership model:

const client = new CopilotClient({
  shell: {
    initProfile: "non-interactive",
    env: {
      VSCODE_PYTHON_BASH_ACTIVATE: "...",
      VSCODE_PYTHON_PWSH_ACTIVATE: "...",
    },
    initScripts: [
      { shell: "bash", path: "/path/to/generated-python-bash-init.sh" },
      { shell: "powershell", path: "C:\\path\\to\\generated-python-pwsh-init.ps1" },
    ],
  },
});

Or, if maintainers prefer per-session overrides, the same shape could be accepted on createSession(...) and/or session.rpc.options.update(...):

const session = await client.createSession({
  shell: {
    initProfile: "non-interactive",
    env: {
      VSCODE_PYTHON_BASH_ACTIVATE: "...",
      VSCODE_PYTHON_PWSH_ACTIVATE: "...",
    },
    initScripts: [
      { shell: "bash", path: "/path/to/generated-python-bash-init.sh" },
      { shell: "powershell", path: "C:\\path\\to\\generated-python-pwsh-init.ps1" },
    ],
  },
});
await session.rpc.options.update({
  shell: {
    initProfile: "non-interactive",
    env: {
      VSCODE_PYTHON_BASH_ACTIVATE: "...",
    },
    initScripts: [
      { shell: "bash", path: "/path/to/generated-python-bash-init.sh" },
    ],
  },
});

The main thing I am looking for is not necessarily a specific scope, but a supported SDK-owned shell startup API with clear semantics:

  • If it is runtime/client-scoped, it should be clear that the shell startup material applies to built-in shell tool child processes spawned by that SDK runtime.
  • If it is session-scoped, it should be clear how this interacts with shared/resumed sessions and multiple clients.
  • In either case, it should be explicit host-provided startup material, not automatic sourcing of user rc/profile files.

/cc @MRayermannMSFT

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions