Skip to content

Repository files navigation

Glean PowerShell SDK

PowerShell Glean .NET

A PowerShell SDK for the Glean REST APIs. Every operation in Glean's published OpenAPI specification, as a cmdlet — with an offline mode that needs no credentials and shares its corpus with glean-code-cli.

Import-Module Glean
Invoke-GleanSearch -Query 'quarterly planning' | Select-Object title, url

That works before you have a token. With no credential configured the module answers from a local corpus of seventy interlinked documents, so the whole surface is explorable offline.

Contents

Highlights

  • Complete coverage, provably. 126 cmdlets over all 135 operations in Glean OpenAPI spec 0.9.0 — 91 Client API, 38 Indexing, 6 Custom Metadata — plus 11 core cmdlets. Coverage is enforced at build time: an operation with no cmdlet fails the build. See docs/SPEC_CONFORMANCE.md.
  • Two implementations that are actually identical. A script module and a compiled binary module, generated from one contract file and checked against one Pester suite. A dedicated parity suite asserts they expose the same commands, parameters and parameter sets and return the same objects.
  • Offline mock mode that is one coherent index. A URL from Invoke-GleanSearch resolves in Get-GleanDocument, summarises to the same document, and appears as a real citation in Send-GleanChatMessage. The corpus file is shared byte-for-byte with glean-code-cli, and a parity test runs both implementations over the same queries and requires identical rankings.
  • Credentials that cannot leak. Resolved tokens are held outside the connection object, so Get-GleanConnection | ConvertTo-Json, a transcript, or an error dump carries a source label and a masked hint — never the value.
  • Four credential paths: API token, secure environment references, SecretManagement vaults, and browser SSO (OAuth 2.1 + PKCE).
  • PowerShell conventions, enforced not assumed. Approved verbs, singular nouns, -WhatIf on everything that changes state, comment-based help with a runnable example on every command, PSScriptAnalyzer clean. Each of those is a test, not a claim — 1,831 assertions per implementation, at 78% coverage.

Two implementations

Glean Glean.Compiled
Form Script module (.psm1) Binary module (.dll, net8.0)
Best for Reading and modifying the source; no build step Fast import; no source on disk
Import time 118 ms 15 ms
Commands 137 functions + 2 aliases 137 cmdlets + 2 aliases
Needs a build no yes (./build.ps1 -Task Build)

Import time is the median of three cold processes on an M-series Mac with PowerShell 7.6 — the script module parses 152 files, the compiled one loads one assembly. It only matters if you import Glean in a short-lived script or a prompt function; for an interactive session either is imperceptible.

They expose the same surface and return the same objects. Install whichever suits your environment — but do not import both into one session, because they export the same command names.

Install

Requires PowerShell 7.4 or later.

# from a local checkout
Import-Module ./src/Glean/Glean.psd1

# or the compiled twin, after ./build.ps1 -Task Build
Import-Module ./src/Glean.Compiled/bin/Release/net8.0/Glean.Compiled.psd1

Take the guided offline tour — search, chat with citations, follow a citation to its document, summarise it, check permissions, run an agent, inspect the index:

./demo/Invoke-GleanTour.ps1

Connecting

# a secure reference: config.json holds the reference name, never the secret
$env:GLEAN_CLIENT_TOKEN = 'glean_...'
Connect-Glean -Instance acme -Token token.secure.client

# a SecretManagement vault
Connect-Glean -Instance acme -SecretName GleanProd -SecretVault Work

# prompt for the token without it reaching PSReadLine history
Connect-Glean -Instance acme -Credential (Get-Credential -UserName glean-prod)

# browser sign-in, OAuth 2.1 + PKCE
Connect-Glean -Instance acme -Sso

-Instance takes an instance id (acme), a backend hostname (acme-be.glean.com) or a full URL.

Then check what the session is really using:

Get-GleanConnection
Test-GleanConnection

Test-GleanConnection emits one object per check, so a script can gate on it:

if (Test-GleanConnection | Where-Object Status -eq 'Fail') { throw 'Glean is not usable' }

Credential references

Reference Resolves from Stored on disk
token.secure.client $env:GLEAN_CLIENT_TOKEN the reference name only
token.secure.indexing $env:GLEAN_INDEXING_TOKEN the reference name only
env:NAME $env:NAME the reference name only
secret:NAME a SecretManagement vault the reference name only
a literal token never written; kept in memory

The first two names are the same ones glean-code-cli uses, so a config written by either tool is understood by the other.

Mock mode

With no credential resolved, Connect-Glean -Mode Auto (the default) falls back to Mock rather than firing an unauthenticated request that would only 401.

Mock mode is not a stub. Seventy documents across five faux datasources (gdrive, confluence, jira, github, slack) cross-reference each other — the checkout incident appears as a Jira ticket, a Slack war room, a Confluence postmortem and the GitHub PR that fixed it.

Connect-Glean -Mock
Get-GleanMockCorpus                            # 70 documents, 8 people, 5 datasources
Get-GleanMockCorpus -Document -Datasource jira
Set-GleanMockCorpus -Path ./my-corpus.json     # bring your own

The corpus is shared with glean-code-cli. data/mock-corpus.json is exported from the CLI's built-in corpus and loads back into it unchanged:

export GLEAN_MOCK_CORPUS=/path/to/glean-powershell/data/mock-corpus.json
python3 -m glean_code          # the CLI now reads the same documents

The ranking is a deliberate port, not a reimplementation: the same scoring weights, tie-breaks, snippet selection and result envelope. tests/Integration/MockParity.Tests.ps1 runs the Python implementation and this one over the same queries and requires identical output — same documents, same order, same snippets, same tracking tokens.

Command surface

Surface Operations Example cmdlets
Search, chat and summarize 18 Invoke-GleanSearch, Send-GleanChatMessage, Get-GleanChat, Get-GleanDocumentSummary
Agents and tools 15 Invoke-GleanAgent, Find-GleanAgent, Get-GleanTool, Invoke-GleanTool
Documents, people and entities 6 Get-GleanDocument, Get-GleanDocumentPermission, Get-GleanPerson, Get-GleanEntity
Knowledge management 29 New-GleanAnswer, Get-GleanCollection, New-GleanPin, Get-GleanShortcut, Set-GleanVerification
Governance and DLP 14 Get-GleanPolicy, New-GleanReport, Set-GleanDocumentVisibility, Save-GleanFindingExport
Datasources and auth 6 Get-GleanDatasourceConfiguration, Update-GleanDatasourceCredential, New-GleanAuthToken
Insights and activity 3 Get-GleanInsight, Send-GleanActivity, Send-GleanFeedback
Client API total 91
Indexing — permissions and groups 11 Set-GleanIndexMembership, Sync-GleanIndexGroup, Set-GleanIndexDocumentPermission
Indexing — troubleshooting 9 Get-GleanIndexDebugStatus, Test-GleanIndexDocumentAccess, Get-GleanIndexDocumentCount
Indexing — people and teams 7 Set-GleanIndexEmployee, Sync-GleanIndexTeam, Start-GleanIndexEmployeeProcessing
Indexing — documents 6 Set-GleanIndexDocument, Sync-GleanIndexDocument, Start-GleanIndexDocumentProcessing
Indexing — datasources, shortcuts, auth 5 Set-GleanIndexDatasource, Sync-GleanIndexShortcut, Update-GleanIndexToken
Indexing API total 38
Custom Metadata 6 Set-GleanMetadataSchema, Set-GleanDocumentMetadata, Submit-GleanDatasourceData
Spec total 135 covered by 126 cmdlets
Core, not from the spec Connect-Glean, Test-GleanConnection, Invoke-GleanApi, Get-GleanApiOperation

Fewer cmdlets than operations because a Get- cmdlet fronts both the list and the fetch form of an endpoint pair — see naming rules.

Find the cmdlet for any endpoint you know by path:

Get-GleanApiOperation -Path '*summarize*'
Get-GleanApiOperation | Group-Object Api | Select-Object Name, Count

Naming rules

Every command is Verb-GleanNoun with a verb from Get-Verb and a singular noun. Beyond the obvious four:

Verb Means
Sync bulk upload that makes the index match your source of truth
Start begin asynchronous server-side processing
Save write a returned file (CSV, image, attachment) to disk
Send push data one way, expecting only an acknowledgement
Find search a container
Request begin an authorization flow

Get- cmdlets list when given no identifier and fetch when given one, rather than shipping a separate List- command (List is not an approved verb).

These rules are checked, not documented and hoped for: tests/Unit/Naming.Tests.ps1 asserts every exported command satisfies each one.

Pipeline behaviour

Cmdlets emit the interesting part of a response, not the envelope:

Invoke-GleanSearch -Query 'incident' | Select-Object title, url    # results, not {results, facets, cursor}
Invoke-GleanSearch -Query 'incident' -Raw                          # the whole envelope

When a response pages, the cursor is attached to each emitted object as GleanCursor, so paging does not force -Raw.

Safety

Everything that changes state supports -WhatIf and -Confirm. Deletions and bulk operations that replace a datasource's contents are ConfirmImpact High, so they prompt by default.

Remove-GleanIndexDocument -Datasource gdrive -ObjectType Document -Id doc_1 -WhatIf
# What if: Performing the operation "Remove-GleanIndexDocument" on target "/api/index/v1/deletedocument (gdrive)".

When a cmdlet does not exist

Invoke-GleanApi calls any path directly, through the same retry, error mapping and credential selection as every generated cmdlet:

Invoke-GleanApi -Path /rest/api/v1/search -Body @{ query = 'pto policy'; pageSize = 3 }
Invoke-GleanApi -Path /api/index/v1/getdocumentcount -Body @{ datasource = 'gdrive' }

The API family — and therefore which token signs the call — is inferred from the path unless you pass -Api.

Building and testing

./build.ps1                 # generate, build, analyze, test, docs, package
./build.ps1 -Task Test
./build.ps1 -Task Analyze
./build.ps1 -Task Test -SkipPython   # skip generation and the Python parity suite

Run the suite against either implementation:

$env:GLEAN_TEST_MODULE = 'Compiled'
./build.ps1 -Task Test
Suite What it pins down
Unit/Naming verbs, nouns, help, ShouldProcess, manifest exports, source hygiene
Unit/Http URI building, retry and backoff, error mapping, response unrolling
Unit/Credential credential resolution, and that no token can reach the output
Integration/Coverage every one of the 126 cmdlets actually runs, and honours -WhatIf
Integration/MockParity this SDK and glean-code-cli rank the shared corpus identically
Integration/Transport the live request path, driven through a local HTTP server: auth headers, retry, error mapping, downloads
Integration/TwinParity the script and compiled modules are indistinguishable
Integration/Resilience a corrupt config, a hand-edited corpus, an unresolvable credential, an unreachable host

How it is generated

The cmdlets are not hand-written. Four tools turn the published spec into both modules, and each one fails the build rather than emitting something wrong:

client_rest.yaml + indexing.yaml
        │  tools/extract_contract.py      resolve $refs, flatten to one contract
        ▼
contract/glean-api.json                   135 operations
        │  tools/build_cmdlet_map.py      name them; reject unapproved verbs,
        ▼                                 plural nouns, collisions, uncovered ops
contract/cmdlet-map.json                  126 cmdlets
        │  tools/build_surface.py         resolve parameters, types, sets, help
        ▼
contract/cmdlet-surface.json              491 parameters
        │
        ├── tools/generate_powershell.py ─► src/Glean/Public/*.ps1
        └── tools/generate_csharp.py ─────► src/Glean.Compiled/Cmdlets/Generated/*.cs

Generated output is checked in so it is reviewable in a pull request, and CI fails if regenerating changes anything.

To refresh against a newer spec release:

mkdir -p build/spec && cd build/spec
curl -sSLO https://gleanwork.github.io/open-api/specs/final/client_rest.yaml
curl -sSLO https://gleanwork.github.io/open-api/specs/final/indexing.yaml
cd ../.. && ./build.ps1

Any new operation fails build_cmdlet_map.py until it is given a name, which is the point: coverage cannot silently regress.

Documentation

  • docs/SPEC_CONFORMANCE.md — coverage, naming decisions, and the twelve glean-code-cli divergences this SDK does not inherit
  • docs/MOCK_MODE.md — the shared corpus, how parity with glean-code-cli is proven, and how to bring your own
  • docs/AUTHENTICATION.md — the four credential paths, and why a token cannot reach your output
  • docs/TESTING.md — what each suite pins down
  • docs/cmdlets/ — reference page for all 137 commands
  • Get-Help about_Glean — the conceptual overview
  • Get-Help <command> -Full — every command, with examples

Relationship to glean-code-cli

This SDK is a sibling of glean-code-cli, not a port of it. It shares the CLI's mock corpus, its secure-reference names and its banner, so the two read as one product — but the API layer is generated from Glean's spec rather than hand-written, which is why the CLI's twelve documented divergences do not appear here.

License

MIT. See LICENSE.

Not affiliated with or endorsed by Glean Technologies, Inc.

About

PowerShell SDK for the Glean REST APIs — 137 cmdlets covering all 135 operations in spec 0.9.0, with an offline mock mode shared with glean-code-cli

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages