Skip to content

draft of how to enable shell integration with commands #348

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 46 additions & 7 deletions Draft-Accepted/RFCXXXX-Command-Shell-Integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ However, this typically works for the system and not for a particular user who d
This can also make it more complicated to uninstall tools that place files across the filesystem.

Although the examples here are focused on PowerShell, the design is intended to be generic and can be used by other shells.
However, PowerShell specific implementation details are included.

## Motivation

Expand Down Expand Up @@ -131,26 +132,48 @@ Based on user feedback, there can be a configuration file to disable specific ex

## Specification

### Discovery

A JSON manifest file would be placed alongside the executable (or technically anywhere within `$env:PATH`) and discovered by the shell.
Copy link
Contributor

Choose a reason for hiding this comment

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

We should make it clear that JSON file is for a individual command line tool. Is there a naming convention that must be followed? How is the manifest file distinguished from other possible json files?

Suggested change
A JSON manifest file would be placed alongside the executable (or technically anywhere within `$env:PATH`) and discovered by the shell.
A tool specific JSON manifest file would be placed alongside the tool executable (or technically anywhere within `$env:PATH`) and discovered by the shell.

All paths are relative to the location of the manifest file and must use the forward slash path separator.

On Unix systems tools are sometimes synlinked to `/usr/bin`, for example, and on Windows, MSIX installed CLI tools are reparse points
to a different location.
Shells should look for the manifest file in the target location of a symlink or reparse point in addition to within `$env:PATH`.

In the case that multiple JSON manifests are for the same executable, the last one wins.
So if a user wants to override a manifest shipped with a tool, they can place their own in a location that is later in `$env:PATH`.

### Command shell integration manifest

The JSON manifest file name would be `<name>.command.json`.
The `<name>` portion is only used to differentiate between multiple manifests and does not need to match the executable name,
but it is recommended to do so.
The JSON manifest file name would be `<name>.<author>.command.json`.

- `<name>` should match the executable name without the extension.
- `<author>` is the name of the author or organization that created the tool to avoid collisions.

```json
{
"$schema": "https://schemas.microsoft.com/commandshell/2023/05/01/command.json",
"executable": "az",
"version": "1.0.0"
"version": "1.0.0",
"author": "Microsoft",
"description": "Azure CLI",
"copyright": "Copyright (c) Microsoft",
"license": "https://github.com/Azure/azure-cli/blob/dev/LICENSE",
}
```

The `$schema` includes the version of the manifest with the URL pointing to a published JSON schema.
The `executable` is the name of the executable that the manifest is for and expected to be found in `$env:PATH`
The `version` is the version of the manifest for the tool and only used for informational purposes.
The mandatory fields are:
Copy link
Contributor

Choose a reason for hiding this comment

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

When are manifest files probed for ... on first time tool execution? Is tool manifest information cached? I assume manifest validation is performed at that time and an error is displayed if validation fails? Will there be a shell command to load/validate a tool manifest file (for tool development/debugging purposes)?


- `$schema` includes the version of the manifest with the URL pointing to a published JSON schema.
- `executable` is the name of the executable that the manifest is for and expected to be found in `$env:PATH`
- `version` is the version of the manifest for the tool and only used for informational purposes.

The optional fields are:

- `author` is the name of the author or organization that created the tool.
- `description` is a short description of the tool.
- `license` is the URL to the license for the tool.

### Structured Output and Custom Formatting Registration

Expand Down Expand Up @@ -180,6 +203,11 @@ JSON output can optionally include a `$typeNames` member which is an array of st
PowerShell would use this as the same as the `TypeNames` member of a PSObject for formatting.
Future enhancement would support a JSON defined formatting schema that could be used by other shells.

Users may want to selectively disable structured output for a tool.
How this is done is shell specific.
For PowerShell, a user could set the environment variable `COMMAND_SHELL_STRUCTURED_OUTPUT` to `none` to disable structured output for all tools
and remove that environment variable to re-enable it.

### Tab Completion Registration

Within the same manifest, a tool can indicate it supports tab completion.
Expand Down Expand Up @@ -234,6 +262,9 @@ or a shell specific script:
Multiple shells can be specified and up to the shell to determine which one to use.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Multiple shells can be specified and up to the shell to determine which one to use.
Multiple shells can be specified and it is up to the shell to determine which one to use.

Both a `command` and `script` can be specified, but only one of each and also up to the shell to determine which one to use.

In this PowerShell example, the `az-completion.ps1` would be called one time to register the argument completer.
A different shell may decide to call the script for each tab completion request.

### Help Registration

The same manifest may define a path to the help content:
Expand Down Expand Up @@ -276,6 +307,14 @@ Specifically for PowerShell, a command may also want to optionally register a Pr
Similar to `tabCompletion`, alternate shells can choose to adopt their own mechanism for registering these extensions
under their shell specific key.

In the case of PowerShell, predictors and feedback providers are assemblies so the value is the path to the assembly
instead of a `.ps1` script.
To enable support for MSIX installed tools and not load the dll directly from their location, PowerShell will
Copy link
Member

Choose a reason for hiding this comment

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

The API to resolve the actual location of a MSIX application is undocumented IIRC. Is there a documented API available today?

Copy link
Member Author

Choose a reason for hiding this comment

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

I thought I had resolved this with the APPX team. I'll follow-up so we can use this.

copy the dll to the user's folder if it is not already there (SHA256 hash comparison) and load it from there:

- On Unix, the dll will be copied to `$HOME/.local/share/powershell/Predictors` and `$HOME/.local/share/powershell/FeedbackProviders`
Copy link
Contributor

Choose a reason for hiding this comment

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

At what point are the tool binaries copied? I hope it is not done at tool runtime. I feel we should distinguish between tool runtime and set-up time, so that there is a separate tool registration step when predictors/providers are registered.

Otherwise, I feel some IT users will feel uncomfortable having binaries copied on their systems, without their knowledge.

- On Windows, the dll will be copied to `$HOME\AppData\Local\Microsoft\PowerShell\Predictors` and `$HOME\AppData\Local\Microsoft\PowerShell\FeedbackProviders`

## Alternate Proposals and Considerations

Users may decide they don't want to use a tools shell integration feature by selectively disabling it.
Expand Down