Skip to content

Install Auto Mode Gate

Install the package only after reviewing its source. OpenCode plugins and Pi extensions run with the user’s system permissions.

Choose the host that should load the gate. Each host keeps its own installation and policy paths.

Declare the package in the plugin array of your project or global opencode.json:

{
"$schema": "https://opencode.ai/config.json",
"plugin": ["auto-mode-gate@0.4.3"]
}

Merge that entry into the existing array without removing other plugins or configuration. OpenCode resolves configured npm plugins when it starts.

You can also install it for the current project:

opencode plugin auto-mode-gate@0.4.3

Add --global to install it for every project. Verify the resolved plugin list:

opencode debug config

The resolved plugin list must contain the Auto Mode Gate entry. This proves discovery and configuration resolution, not pre-tool enforcement. Use the isolated host integration described under Verify and operate for the behavioral check.

The source loader flow uses one small loader file and does not edit host settings. Run the commands from the checkout root, keep the checkout at the same path, and restart the host after installing the loader. Set $scope to project or global; $targetProject is used only for project scope.

Terminal window
$scope = "project"
$targetProject = "C:\path\to\project"
if ($scope -notin @("project", "global")) {
throw "scope must be project or global"
}
function Assert-SafeDirectoryPath([string]$Leaf, [string]$Root) {
$candidate = $Leaf
while (-not (Test-Path -LiteralPath $candidate)) {
$candidate = Split-Path -Parent $candidate
if ([string]::IsNullOrEmpty($candidate)) { throw "path escaped its scope root" }
}
$current = Get-Item -LiteralPath $candidate -Force
while ($true) {
if ($current.Attributes -band [System.IO.FileAttributes]::ReparsePoint) {
throw "path must not contain a symlink"
}
if ($current.FullName -eq $Root) { return }
$current = $current.Parent
if ($null -eq $current) { throw "path escaped its scope root" }
}
}
$source = [System.Uri]::new((Resolve-Path .\src\opencode-runtime.ts).Path).AbsoluteUri
$pluginRoot = if ($scope -eq "project") {
$scopeRoot = (Get-Item -LiteralPath (Resolve-Path -LiteralPath $targetProject).Path -Force).FullName
Join-Path $scopeRoot ".opencode\plugins"
} elseif ($env:OPENCODE_CONFIG_DIR) {
if (-not [System.IO.Path]::IsPathRooted($env:OPENCODE_CONFIG_DIR) -or
-not (Test-Path -LiteralPath $env:OPENCODE_CONFIG_DIR -PathType Container)) {
throw "OPENCODE_CONFIG_DIR must be an existing absolute directory"
}
$configuredRoot = Get-Item -LiteralPath $env:OPENCODE_CONFIG_DIR -Force
if ($configuredRoot.Attributes -band [System.IO.FileAttributes]::ReparsePoint) {
throw "OPENCODE_CONFIG_DIR must not be a symlink"
}
$scopeRoot = $configuredRoot.FullName
Join-Path $scopeRoot "plugins"
} else {
$scopeRoot = (Get-Item -LiteralPath $HOME -Force).FullName
Join-Path $scopeRoot ".config\opencode\plugins"
}
Assert-SafeDirectoryPath $pluginRoot $scopeRoot
New-Item -ItemType Directory -Force $pluginRoot | Out-Null
Assert-SafeDirectoryPath $pluginRoot $scopeRoot
$loaderPath = Join-Path $pluginRoot "auto-mode-gate.ts"
$loaderBytes = [System.Text.UTF8Encoding]::new($false).GetBytes(
"export { AutoModeGatePlugin } from `"$source`";"
)
$loaderStream = $null
$loaderCreated = $false
try {
$loaderStream = [System.IO.File]::Open(
$loaderPath,
[System.IO.FileMode]::CreateNew,
[System.IO.FileAccess]::Write,
[System.IO.FileShare]::None
)
$loaderCreated = $true
$loaderStream.Write($loaderBytes, 0, $loaderBytes.Length)
$loaderStream.Flush($true)
} catch {
if ($loaderCreated) {
$loaderStream.Dispose()
$loaderStream = $null
Remove-Item -LiteralPath $loaderPath -Force
}
throw
} finally {
if ($null -ne $loaderStream) { $loaderStream.Dispose() }
}

Verify discovery:

Terminal window
if ($scope -eq "project") {
Push-Location $targetProject
try { opencode debug config } finally { Pop-Location }
} else {
opencode debug config
}

OpenCode 1.18.18 has no plugin removal subcommand. Use opencode debug config to locate the configuration that supplied the plugin, remove only the matching Auto Mode Gate entry from its plugin array, restart OpenCode, and confirm that the plugin no longer appears.

For a source installation, resolve the same scope as the installation block. In the same PowerShell session, delete only the loader or extension directory calculated above:

Terminal window
Remove-Item -LiteralPath (Join-Path $pluginRoot "auto-mode-gate.ts")
Remove-Item -LiteralPath (Join-Path $extensionRoot "index.ts")
if ((Get-ChildItem -LiteralPath $extensionRoot -Force).Count -eq 0) {
Remove-Item -LiteralPath $extensionRoot
}

Run only the line for the host you installed. If those variables are no longer available, repeat the path calculation without creating directories or writing a loader, inspect the resolved path, and then remove it.