From 4a0139234378ee385b73d61fb902e1537d7ea0a4 Mon Sep 17 00:00:00 2001 From: Steve Calvert Date: Sun, 19 Jul 2026 14:15:52 -0700 Subject: [PATCH] feat(skills): reframe generated skill as thin router to agent-help MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The generated SKILL.md no longer duplicates per-command documentation: it teaches agents to run 'glean agent-help' as the version-accurate source of truth, keeps a registry-generated when-to-use command map for skill triggering, and drops the static reference/*.md files (the generator also cleans up the retired reference dir and legacy per-command skill dirs). The duplicated subcommand/description maps are deleted — that content now lives in the schema registry's WhenToUse. Regenerates the checked-in skills/ directory. Co-Authored-By: Claude Fable 5 --- internal/skills/generator.go | 365 +++----------------- internal/skills/generator_test.go | 110 +++--- skills/glean-cli/SKILL.md | 116 +++---- skills/glean-cli/reference/activity.md | 37 -- skills/glean-cli/reference/agents.md | 41 --- skills/glean-cli/reference/announcements.md | 39 --- skills/glean-cli/reference/answers.md | 41 --- skills/glean-cli/reference/api.md | 35 -- skills/glean-cli/reference/chat.md | 34 -- skills/glean-cli/reference/collections.md | 43 --- skills/glean-cli/reference/documents.md | 40 --- skills/glean-cli/reference/entities.md | 37 -- skills/glean-cli/reference/insights.md | 37 -- skills/glean-cli/reference/messages.md | 36 -- skills/glean-cli/reference/pins.md | 41 --- skills/glean-cli/reference/search.md | 46 --- skills/glean-cli/reference/shortcuts.md | 42 --- skills/glean-cli/reference/tools.md | 38 -- skills/glean-cli/reference/verification.md | 39 --- 19 files changed, 146 insertions(+), 1071 deletions(-) delete mode 100644 skills/glean-cli/reference/activity.md delete mode 100644 skills/glean-cli/reference/agents.md delete mode 100644 skills/glean-cli/reference/announcements.md delete mode 100644 skills/glean-cli/reference/answers.md delete mode 100644 skills/glean-cli/reference/api.md delete mode 100644 skills/glean-cli/reference/chat.md delete mode 100644 skills/glean-cli/reference/collections.md delete mode 100644 skills/glean-cli/reference/documents.md delete mode 100644 skills/glean-cli/reference/entities.md delete mode 100644 skills/glean-cli/reference/insights.md delete mode 100644 skills/glean-cli/reference/messages.md delete mode 100644 skills/glean-cli/reference/pins.md delete mode 100644 skills/glean-cli/reference/search.md delete mode 100644 skills/glean-cli/reference/shortcuts.md delete mode 100644 skills/glean-cli/reference/tools.md delete mode 100644 skills/glean-cli/reference/verification.md diff --git a/internal/skills/generator.go b/internal/skills/generator.go index 0e5a785..305425d 100644 --- a/internal/skills/generator.go +++ b/internal/skills/generator.go @@ -1,4 +1,7 @@ -// Package skills generates SKILL.md files from the CLI's own schema registry. +// Package skills generates a single thin SKILL.md from the CLI's schema +// registry. The skill deliberately contains almost no command detail: its job +// is to route agents to `glean agent-help`, which generates version-accurate +// usage from the installed binary and is therefore the source of truth. // // Usage: glean generate-skills [--output-dir skills/] package skills @@ -7,7 +10,6 @@ import ( "fmt" "os" "path/filepath" - "sort" "strings" "text/template" @@ -17,149 +19,10 @@ import ( // rootSkillName is the directory and frontmatter name for the root discovery skill. const rootSkillName = "glean-cli" -// skillPrefix is prepended to command names to form skill directory and -// frontmatter names (e.g. "glean-cli-search"). +// skillPrefix matches legacy per-command skill directory names +// (e.g. "glean-cli-search") for cleanup. const skillPrefix = rootSkillName + "-" -// subcommandMap provides human-friendly descriptions for subcommands that -// the schema registry doesn't capture (schemas are per-namespace, not per-sub). -// Keys are "namespace.subcommand". -var subcommandMap = map[string]string{ - "agents.list": "List all available agents", - "agents.get": "Get details of a specific agent", - "agents.schemas": "Get input/output schemas for an agent", - "agents.run": "Run an agent", - "answers.list": "List all curated answers", - "answers.get": "Get a specific answer", - "answers.create": "Create a new answer", - "answers.update": "Update an existing answer", - "answers.delete": "Delete an answer", - "announcements.create": "Create a new announcement", - "announcements.update": "Update an existing announcement", - "announcements.delete": "Delete an announcement", - "collections.list": "List all collections", - "collections.get": "Get a specific collection", - "collections.create": "Create a new collection", - "collections.update": "Update a collection", - "collections.delete": "Delete a collection", - "collections.add-items": "Add documents to a collection", - "collections.delete-item": "Remove a document from a collection", - "documents.get": "Retrieve document metadata by URL or ID", - "documents.summarize": "Generate an AI summary of a document", - "documents.get-by-facets": "Retrieve documents matching facet filters", - "documents.get-permissions": "Inspect who has access to a document", - "entities.list": "List entities by type and query", - "entities.read-people": "Get detailed people profiles", - "insights.get": "Get analytics data", - "messages.get": "Retrieve a specific message", - "pins.list": "List all pins", - "pins.get": "Get a specific pin", - "pins.create": "Create a new pin", - "pins.update": "Update a pin", - "pins.remove": "Remove a pin", - "shortcuts.list": "List all shortcuts", - "shortcuts.get": "Get a specific shortcut", - "shortcuts.create": "Create a new shortcut", - "shortcuts.update": "Update an existing shortcut", - "shortcuts.delete": "Delete a shortcut", - "tools.list": "List available platform tools", - "tools.run": "Execute a platform tool", - "verification.list": "List documents pending verification", - "verification.verify": "Mark a document as verified", - "verification.remind": "Send a verification reminder", - "activity.report": "Report a user activity event", - "activity.feedback": "Submit feedback on search results", -} - -// skillDescription maps command names to richer descriptions for the SKILL.md -// frontmatter. These are tuned for agent skill triggering. -var skillDescription = map[string]string{ - "search": "Search across company knowledge with the Glean CLI. Use when finding documents, policies, engineering docs, or any information across enterprise data sources.", - "chat": "Chat with Glean Assistant from the command line. Use when asking questions, summarizing documents, or getting AI-powered answers about company knowledge.", - "api": "Make raw authenticated HTTP requests to any Glean REST API endpoint. Use when no dedicated command exists or for advanced API access.", - "agents": "List, inspect, and run Glean AI agents. Use when discovering available agents, viewing agent schemas, or invoking agents programmatically.", - "documents": "Retrieve, summarize, and inspect documents indexed by Glean. Use when getting document content, summaries, permissions, or metadata by URL.", - "collections": "Manage curated document collections in Glean. Use when creating, updating, or organizing themed sets of documents.", - "entities": "Look up people, teams, and custom entities in Glean. Use when finding employees, org structure, team members, or expertise.", - "answers": "Manage curated Q&A pairs in Glean. Use when creating, updating, or listing company-approved answers to common questions.", - "shortcuts": "Manage Glean go-links (shortcuts). Use when creating, listing, updating, or deleting short URL aliases like go/wiki.", - "pins": "Manage promoted search results (pins) in Glean. Use when pinning specific documents to appear first for certain queries.", - "announcements": "Manage time-bounded company announcements in Glean. Use when creating, updating, or deleting announcements that surface across the Glean UI.", - "activity": "Report user activity and submit feedback to Glean. Use when logging user interactions or providing relevance feedback on search results.", - "verification": "Manage document verification and review workflows in Glean. Use when verifying document accuracy, listing pending verifications, or sending review reminders.", - "tools": "List and run Glean platform tools. Use when discovering available platform tools or executing them programmatically.", - "messages": "Retrieve indexed messages from Slack, Teams, and other messaging platforms via Glean. Use when searching for or reading specific messages.", - "insights": "Retrieve search and usage analytics from Glean. Use when analyzing search patterns, popular queries, or platform adoption metrics.", -} - -// FlagInfo holds rendered flag data for templates. -type FlagInfo struct { - Name string - Type string - Default string - Description string - Required bool -} - -// SkillData holds all data needed to render a SKILL.md template. -type SkillData struct { - Prefix string - RootSkill string - Name string - Description string - Command string - SchemaDesc string - Flags []FlagInfo - Subcommands []SubcommandInfo - Example string - HasDryRun bool -} - -// SubcommandInfo describes a subcommand. -type SubcommandInfo struct { - Name string - Description string -} - -var referenceTmpl = template.Must(template.New("reference").Parse(`# glean {{ .Command }} - -{{ .SchemaDesc }} - -` + "```bash" + ` -glean {{ .Command }}{{ if .Subcommands }} {{ end }} [flags] -` + "```" + ` -{{ if .Subcommands }} -## Subcommands - -| Subcommand | Description | -|------------|-------------| -{{ range .Subcommands -}} -| ` + "`{{ .Name }}`" + ` | {{ .Description }} | -{{ end }}{{ end }} -## Flags - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -{{ range .Flags -}} -| ` + "`{{ .Name }}`" + ` | {{ .Type }} | {{ .Default }} | {{ .Description }}{{ if .Required }} **(required)**{{ end }} | -{{ end }} -## Examples - -` + "```bash" + ` -{{ .Example }} -` + "```" + ` - -## Discovering Commands - -` + "```bash" + ` -# Show machine-readable schema for this command -glean schema {{ .Command }} - -# List all available commands -glean schema | jq '.commands' -` + "```" + ` -`)) - var rootTmpl = template.Must(template.New("root").Parse(`--- name: {{ .RootSkill }} description: "Glean CLI: access company knowledge, search documents, chat with Glean Assistant, look up people, and manage enterprise content. Use when the user asks about internal docs, company information, people, policies, or enterprise data." @@ -168,86 +31,53 @@ compatibility: Requires the glean binary on $PATH. Install via brew install glea # Glean CLI -The ` + "`glean`" + ` command-line tool provides authenticated access to your company's Glean instance. It can search documents, chat with Glean Assistant, look up people and teams, manage collections, and more. - -## When to Use - -Use the Glean CLI when the user: +The ` + "`glean`" + ` command-line tool provides authenticated access to your company's Glean instance. -- Asks about internal documents, policies, wikis, or company knowledge -- Wants to find people, teams, or org structure -- Needs to search across enterprise data sources (Confluence, Jira, Google Drive, Slack, etc.) -- Asks questions that require company-specific context -- Wants to manage Glean resources (collections, shortcuts, pins, announcements) +## Source of truth: ask the binary, not this file -## Installation +This skill is intentionally thin. The CLI describes itself — always start with: ` + "```bash" + ` -brew install gleanwork/tap/glean-cli +glean agent-help # environment context + command map with when-to-use guidance +glean agent-help [sub] # exact flags, payload shapes, examples for one command +glean agent-help --json # machine-readable ` + "```" + ` +The output is generated from the installed binary, so it matches the version +on this machine exactly. **When anything below (or in any other document) +disagrees with ` + "`glean agent-help`" + `, trust ` + "`glean agent-help`" + `.** +It also reports whether the environment is authenticated and which API surface +(platform vs legacy) is active. + ## Authentication ` + "```bash" + ` -# Browser-based OAuth (interactive — recommended) -glean auth login - -# Verify credentials -glean auth status +glean auth login # browser-based OAuth (interactive) +glean auth status # verify credentials -# CI/scripting (no interactive setup needed) +# CI/scripting export GLEAN_API_TOKEN=your-token export GLEAN_SERVER_URL= ` + "```" + ` -Credentials resolve in this order: environment variables → system keyring → ~/.glean/config.json. - -## CLI Syntax - -` + "```bash" + ` -glean [subcommand] [flags] -` + "```" + ` - -### Global Flags - -| Flag | Description | -|------|-------------| -| --output | json (default), ndjson (one result per line), text | -| --fields | Dot-path field projection (e.g. results.document.title,results.document.url) | -| --json | Complete JSON request body (overrides all other flags) | -| --dry-run | Print request body without sending | +## Command map -## Schema Introspection - -Always call ` + "`glean schema `" + ` before invoking a command you haven't used before. - -` + "```bash" + ` -glean schema | jq '.commands' # list all commands -glean schema search | jq '.flags' # flags for search -` + "```" + ` +| Command | When to use | API | +|---------|-------------|-----| +{{ range .Commands -}} +| ` + "`glean {{ .Name }}`" + ` | {{ .WhenToUse }} | {{ .Surface }} | +{{ end }} +(Regenerate this table's live equivalent anytime with ` + "`glean agent-help`" + `.) -## Security Rules +## Ground rules - **Never** output API tokens or secrets directly - **Always** use --dry-run before write/delete operations in automated pipelines -- Prefer environment variables over config files for CI/CD - -## Error Handling - -All errors go to stderr; stdout contains only structured output. -Exit code 0 = success, non-zero = error. - -## Available Commands - -| Command | Description | -|---------|-------------| -{{ range .Commands -}} -| [glean {{ .Name }}](reference/{{ .Name }}.md) | {{ .Description }} | -{{ end }} +- All errors go to stderr; stdout contains only structured output. Exit code 0 = success. ## Previously installed per-command skills? -Earlier versions of this project shipped one skill per command (` + "`glean-cli-search`" + `, ` + "`glean-cli-pins`" + `, etc.). Those are superseded by this consolidated skill. If you still have them installed, remove them with: +Earlier versions of this project shipped one skill per command (` + "`glean-cli-search`" + `, ` + "`glean-cli-pins`" + `, etc.) and static per-command reference files. Those are superseded by ` + "`glean agent-help`" + `. If you still have the old skills installed, remove them with: ` + "```bash" + ` npx -y skills remove -g -y \ @@ -259,18 +89,15 @@ npx -y skills remove -g -y \ ` + "```" + ` `)) -// CommandEntry is used by the shared skill template. +// CommandEntry is a row in the skill's command map, sourced from the schema +// registry (the same data agent-help serves live). type CommandEntry struct { - Name string - Description string -} - -// skipCommands lists commands that should not get their own skill. -var skipCommands = map[string]bool{ - "version": true, + Name string + WhenToUse string + Surface string } -// Generate writes SKILL.md files to outputDir for all registered schemas. +// Generate writes the thin SKILL.md to outputDir. func Generate(outputDir string) error { // Remove any legacy per-command skill directories from earlier versions // of this project so the generator output is always idempotent. @@ -278,18 +105,17 @@ func Generate(outputDir string) error { return fmt.Errorf("cleaning stale skill dirs: %w", err) } - // Generate shared skill - commands := schema.List() var entries []CommandEntry - for _, name := range commands { - if skipCommands[name] { - continue - } + for _, name := range schema.List() { s, err := schema.Get(name) if err != nil { continue } - entries = append(entries, CommandEntry{Name: name, Description: s.Description}) + use := s.WhenToUse + if use == "" { + use = s.Description + } + entries = append(entries, CommandEntry{Name: name, WhenToUse: use, Surface: s.Surface}) } if err := writeRootSkill(outputDir, entries); err != nil { @@ -297,28 +123,14 @@ func Generate(outputDir string) error { } fmt.Fprintf(os.Stderr, " wrote %s/SKILL.md\n", rootSkillName) - // Generate per-command reference files under the root skill. - for _, name := range commands { - if skipCommands[name] { - continue - } - s, err := schema.Get(name) - if err != nil { - continue - } - if err := writeCommandReference(outputDir, name, s); err != nil { - return fmt.Errorf("writing reference for %s: %w", name, err) - } - fmt.Fprintf(os.Stderr, " wrote %s/reference/%s.md\n", rootSkillName, name) - } - fmt.Fprintf(os.Stderr, "\nDone. Skills written to %s/\n", outputDir) return nil } // cleanStaleSkillDirs removes any per-command skill directories from earlier -// layouts of this project (skills/glean-cli-/) while leaving the root -// skill directory and anything unrelated intact. +// layouts of this project (skills/glean-cli-/) and the retired +// per-command reference directory (skills/glean-cli/reference/), while +// leaving the root skill directory and anything unrelated intact. func cleanStaleSkillDirs(outputDir string) error { entries, err := os.ReadDir(outputDir) if err != nil { @@ -341,6 +153,10 @@ func cleanStaleSkillDirs(outputDir string) error { return fmt.Errorf("removing legacy skill dir %s: %w", name, err) } } + // Static per-command reference files are superseded by `glean agent-help`. + if err := os.RemoveAll(filepath.Join(outputDir, rootSkillName, "reference")); err != nil { + return fmt.Errorf("removing retired reference dir: %w", err) + } return nil } @@ -356,87 +172,8 @@ func writeRootSkill(outputDir string, commands []CommandEntry) error { defer f.Close() data := struct { - Prefix string RootSkill string Commands []CommandEntry - }{Prefix: skillPrefix, RootSkill: rootSkillName, Commands: commands} + }{RootSkill: rootSkillName, Commands: commands} return rootTmpl.Execute(f, data) } - -func writeCommandReference(outputDir, name string, s schema.CommandSchema) error { - dir := filepath.Join(outputDir, rootSkillName, "reference") - if err := os.MkdirAll(dir, 0o755); err != nil { - return err - } - f, err := os.Create(filepath.Join(dir, name+".md")) - if err != nil { - return err - } - defer f.Close() - - data := buildSkillData(name, s) - return referenceTmpl.Execute(f, data) -} - -func buildSkillData(name string, s schema.CommandSchema) SkillData { - desc := skillDescription[name] - if desc == "" { - desc = s.Description - } - - // Build flags - var flags []FlagInfo - for flagName, fs := range s.Flags { - def := "" - if fs.Default != nil { - def = fmt.Sprintf("%v", fs.Default) - } - typ := fs.Type - if len(fs.Enum) > 0 { - typ = strings.Join(fs.Enum, " \\| ") - } - flags = append(flags, FlagInfo{ - Name: flagName, - Type: typ, - Default: def, - Description: fs.Description, - Required: fs.Required, - }) - } - sort.Slice(flags, func(i, j int) bool { - return flags[i].Name < flags[j].Name - }) - - // Build subcommands from the subcommandMap - var subs []SubcommandInfo - for key, sdesc := range subcommandMap { - parts := strings.SplitN(key, ".", 2) - if parts[0] == name { - subs = append(subs, SubcommandInfo{Name: parts[1], Description: sdesc}) - } - } - sort.Slice(subs, func(i, j int) bool { - return subs[i].Name < subs[j].Name - }) - - hasDryRun := false - for _, fl := range flags { - if fl.Name == "--dry-run" { - hasDryRun = true - break - } - } - - return SkillData{ - Prefix: skillPrefix, - RootSkill: rootSkillName, - Name: skillPrefix + name, - Description: desc, - Command: name, - SchemaDesc: s.Description, - Flags: flags, - Subcommands: subs, - Example: s.Example, - HasDryRun: hasDryRun, - } -} diff --git a/internal/skills/generator_test.go b/internal/skills/generator_test.go index d046f43..51fdcd2 100644 --- a/internal/skills/generator_test.go +++ b/internal/skills/generator_test.go @@ -17,15 +17,17 @@ func init() { schema.Register(schema.CommandSchema{ Command: "testsearch", Description: "Test search description.", + WhenToUse: "Find test things.", + Surface: schema.SurfacePlatform, Flags: map[string]schema.FlagSchema{ "--query": {Type: "string", Description: "Search query", Required: true}, - "--page": {Type: "integer", Description: "Page number", Default: 1}, }, Example: "glean testsearch --query hello", }) schema.Register(schema.CommandSchema{ Command: "testpins", Description: "Test pins description.", + Surface: schema.SurfaceLegacy, Flags: map[string]schema.FlagSchema{}, Example: "glean testpins list", }) @@ -38,17 +40,11 @@ func runGenerator(t *testing.T) string { return dir } -// registeredCommands returns the list of command names that Generate would -// process (registry minus skipCommands). -func registeredCommands() []string { - var out []string - for _, name := range schema.List() { - if skipCommands[name] { - continue - } - out = append(out, name) - } - return out +func readRootSkill(t *testing.T, dir string) string { + t.Helper() + body, err := os.ReadFile(filepath.Join(dir, rootSkillName, "SKILL.md")) + require.NoError(t, err) + return string(body) } func TestGenerate_WritesRootSkill(t *testing.T) { @@ -60,14 +56,41 @@ func TestGenerate_WritesRootSkill(t *testing.T) { assert.Greater(t, info.Size(), int64(0), "root SKILL.md must be non-empty") } -func TestGenerate_WritesReferenceForEveryCommand(t *testing.T) { +func TestGenerate_PointsToAgentHelpAsSourceOfTruth(t *testing.T) { + content := readRootSkill(t, runGenerator(t)) + + assert.Contains(t, content, "glean agent-help") + assert.Contains(t, strings.ToLower(content), "source of truth") + assert.Contains(t, content, "--json") +} + +func TestGenerate_CommandMapFromRegistry(t *testing.T) { + content := readRootSkill(t, runGenerator(t)) + + assert.Contains(t, content, "`glean testsearch`") + assert.Contains(t, content, "Find test things.") + assert.Contains(t, content, schema.SurfacePlatform) + // testpins has no WhenToUse — Description is the fallback. + assert.Contains(t, content, "Test pins description.") +} + +func TestGenerate_NoReferenceFiles(t *testing.T) { dir := runGenerator(t) - for _, name := range registeredCommands() { - p := filepath.Join(dir, rootSkillName, "reference", name+".md") - _, err := os.Stat(p) - assert.NoError(t, err, "expected reference file for command %q at %s", name, p) - } + _, err := os.Stat(filepath.Join(dir, rootSkillName, "reference")) + assert.True(t, os.IsNotExist(err), "per-command reference files are retired in favor of agent-help") +} + +func TestGenerate_RemovesRetiredReferenceDir(t *testing.T) { + dir := t.TempDir() + stale := filepath.Join(dir, rootSkillName, "reference") + require.NoError(t, os.MkdirAll(stale, 0o755)) + require.NoError(t, os.WriteFile(filepath.Join(stale, "search.md"), []byte("stale"), 0o644)) + + require.NoError(t, Generate(dir)) + + _, err := os.Stat(stale) + assert.True(t, os.IsNotExist(err), "retired reference dir must be cleaned up") } func TestGenerate_NoLegacySkillDirs(t *testing.T) { @@ -140,46 +163,9 @@ func TestCleanStaleSkillDirs_PreservesUnrelatedDirs(t *testing.T) { assert.NoError(t, err, "unrelated dir must not be touched by cleanup") } -func TestReferenceFile_NoFrontmatter(t *testing.T) { - dir := runGenerator(t) - - cmds := registeredCommands() - require.NotEmpty(t, cmds, "at least one registered command required for this test") - - p := filepath.Join(dir, rootSkillName, "reference", cmds[0]+".md") - body, err := os.ReadFile(p) - require.NoError(t, err) - content := string(body) - - assert.False(t, strings.HasPrefix(content, "---"), - "reference file must not start with YAML frontmatter: %s", p) - assert.NotContains(t, content, "PREREQUISITE", - "reference file must not carry the legacy prereq line") -} - -func TestRootSkill_LinksPointToReferenceFiles(t *testing.T) { - dir := runGenerator(t) - - body, err := os.ReadFile(filepath.Join(dir, rootSkillName, "SKILL.md")) - require.NoError(t, err) - content := string(body) - - for _, name := range registeredCommands() { - expected := "(reference/" + name + ".md)" - assert.Contains(t, content, expected, - "root SKILL.md must link to %s", expected) - } - - assert.NotContains(t, content, "../"+skillPrefix, - "root SKILL.md must not contain legacy ../glean-cli-/ links") -} - func TestRootSkill_IncludesMigrationNote(t *testing.T) { - dir := runGenerator(t) - - body, err := os.ReadFile(filepath.Join(dir, rootSkillName, "SKILL.md")) - require.NoError(t, err) - assert.Contains(t, string(body), "npx -y skills remove", + content := readRootSkill(t, runGenerator(t)) + assert.Contains(t, content, "npx -y skills remove", "root SKILL.md must carry the per-command cleanup one-liner") } @@ -209,3 +195,13 @@ func snapshotTree(t *testing.T, root string) map[string]string { require.NoError(t, err) return out } + +// Verify the retired strings module-wide: the generator must no longer strip +// frontmatter into reference files or reference glean schema. +func TestRootSkill_NoStaleSchemaReferences(t *testing.T) { + content := readRootSkill(t, runGenerator(t)) + assert.False(t, strings.Contains(content, "glean schema "), + "skill must route agents to agent-help, not the deprecated schema command") + assert.NotContains(t, content, "(reference/", + "skill must not link to retired reference files") +} diff --git a/skills/glean-cli/SKILL.md b/skills/glean-cli/SKILL.md index aa24c27..5cf2ad6 100644 --- a/skills/glean-cli/SKILL.md +++ b/skills/glean-cli/SKILL.md @@ -6,100 +6,68 @@ compatibility: Requires the glean binary on $PATH. Install via brew install glea # Glean CLI -The `glean` command-line tool provides authenticated access to your company's Glean instance. It can search documents, chat with Glean Assistant, look up people and teams, manage collections, and more. +The `glean` command-line tool provides authenticated access to your company's Glean instance. -## When to Use +## Source of truth: ask the binary, not this file -Use the Glean CLI when the user: - -- Asks about internal documents, policies, wikis, or company knowledge -- Wants to find people, teams, or org structure -- Needs to search across enterprise data sources (Confluence, Jira, Google Drive, Slack, etc.) -- Asks questions that require company-specific context -- Wants to manage Glean resources (collections, shortcuts, pins, announcements) - -## Installation +This skill is intentionally thin. The CLI describes itself — always start with: ```bash -brew install gleanwork/tap/glean-cli +glean agent-help # environment context + command map with when-to-use guidance +glean agent-help [sub] # exact flags, payload shapes, examples for one command +glean agent-help --json # machine-readable ``` +The output is generated from the installed binary, so it matches the version +on this machine exactly. **When anything below (or in any other document) +disagrees with `glean agent-help`, trust `glean agent-help`.** +It also reports whether the environment is authenticated and which API surface +(platform vs legacy) is active. + ## Authentication ```bash -# Browser-based OAuth (interactive — recommended) -glean auth login +glean auth login # browser-based OAuth (interactive) +glean auth status # verify credentials -# Verify credentials -glean auth status - -# CI/scripting (no interactive setup needed) +# CI/scripting export GLEAN_API_TOKEN=your-token export GLEAN_SERVER_URL= ``` -Credentials resolve in this order: environment variables → system keyring → ~/.glean/config.json. - -## CLI Syntax - -```bash -glean [subcommand] [flags] -``` - -### Global Flags - -| Flag | Description | -|------|-------------| -| --output | json (default), ndjson (one result per line), text | -| --fields | Dot-path field projection (e.g. results.document.title,results.document.url) | -| --json | Complete JSON request body (overrides all other flags) | -| --dry-run | Print request body without sending | - -## Schema Introspection - -Always call `glean schema ` before invoking a command you haven't used before. - -```bash -glean schema | jq '.commands' # list all commands -glean schema search | jq '.flags' # flags for search -``` - -## Security Rules +## Command map + +| Command | When to use | API | +|---------|-------------|-----| +| `glean activity` | Report page-view activity events or submit result feedback to improve ranking. | legacy | +| `glean agent-help` | Start every session here: discover available commands, exact flags, payload shapes, and whether the environment is authenticated — without static docs in context. | local | +| `glean agents` | Discover and execute Glean agents (AI workflows). Use schemas first to learn an agent's expected input, then run. | platform | +| `glean announcements` | Publish or manage company announcements surfaced in Glean. | legacy | +| `glean answers` | Manage curated Q&A answer cards shown for matching queries. | legacy | +| `glean api` | Escape hatch: call any Glean API endpoint directly when no dedicated subcommand exists. | raw | +| `glean chat` | Ask Glean AI a question that needs a synthesized, cited answer reasoned over company knowledge, rather than a raw list of results. | legacy | +| `glean collections` | Curate sets of documents into named collections. | legacy | +| `glean documents` | Fetch full metadata, permissions, or an AI summary for documents you already identified (e.g. from search results). | legacy | +| `glean entities` | Look up people (org info, contact details) or other structured entities. | legacy | +| `glean insights` | Retrieve aggregate usage analytics (search/AI adoption metrics) for the deployment. | legacy | +| `glean messages` | Fetch a specific chat/communication message by ID. | legacy | +| `glean pins` | Pin a document to a search query so it always surfaces for that query. | legacy | +| `glean search` | Find documents, messages, and content across all connected datasources. Start here for any 'find X' task. | platform | +| `glean shortcuts` | Create or resolve go-links (short memorable URLs like go/roadmap). | legacy | +| `glean tools` | Discover and execute Glean tools (actions) such as creating tickets or sending messages. | legacy | +| `glean verification` | Track and update document freshness verification (verify docs, send reminders). | legacy | + +(Regenerate this table's live equivalent anytime with `glean agent-help`.) + +## Ground rules - **Never** output API tokens or secrets directly - **Always** use --dry-run before write/delete operations in automated pipelines -- Prefer environment variables over config files for CI/CD - -## Error Handling - -All errors go to stderr; stdout contains only structured output. -Exit code 0 = success, non-zero = error. - -## Available Commands - -| Command | Description | -|---------|-------------| -| [glean activity](reference/activity.md) | Report user activity and feedback. Subcommands: report, feedback. | -| [glean agents](reference/agents.md) | Manage and run Glean agents. Subcommands: list, get, schemas, run. | -| [glean announcements](reference/announcements.md) | Manage Glean announcements. Subcommands: create, update, delete. | -| [glean answers](reference/answers.md) | Manage Glean answers. Subcommands: list, get, create, update, delete. | -| [glean api](reference/api.md) | Make a raw authenticated HTTP request to any Glean REST API endpoint. | -| [glean chat](reference/chat.md) | Have a conversation with Glean AI. Streams response to stdout. | -| [glean collections](reference/collections.md) | Manage Glean collections. Subcommands: create, delete, update, add-items, delete-item. | -| [glean documents](reference/documents.md) | Retrieve and summarize Glean documents. Subcommands: get, get-by-facets, get-permissions, summarize. | -| [glean entities](reference/entities.md) | List and read Glean entities and people. Subcommands: list, read-people. | -| [glean insights](reference/insights.md) | Retrieve Glean usage insights. Subcommands: get. | -| [glean messages](reference/messages.md) | Retrieve Glean messages. Subcommands: get. | -| [glean pins](reference/pins.md) | Manage Glean pins. Subcommands: list, get, create, update, remove. | -| [glean search](reference/search.md) | Search for content in your Glean instance. Results are JSON. | -| [glean shortcuts](reference/shortcuts.md) | Manage Glean shortcuts (go-links). Subcommands: list, get, create, update, delete. | -| [glean tools](reference/tools.md) | List and run Glean tools. Subcommands: list, run. | -| [glean verification](reference/verification.md) | Manage document verification. Subcommands: list, verify, remind. | - +- All errors go to stderr; stdout contains only structured output. Exit code 0 = success. ## Previously installed per-command skills? -Earlier versions of this project shipped one skill per command (`glean-cli-search`, `glean-cli-pins`, etc.). Those are superseded by this consolidated skill. If you still have them installed, remove them with: +Earlier versions of this project shipped one skill per command (`glean-cli-search`, `glean-cli-pins`, etc.) and static per-command reference files. Those are superseded by `glean agent-help`. If you still have the old skills installed, remove them with: ```bash npx -y skills remove -g -y \ diff --git a/skills/glean-cli/reference/activity.md b/skills/glean-cli/reference/activity.md deleted file mode 100644 index 370bb96..0000000 --- a/skills/glean-cli/reference/activity.md +++ /dev/null @@ -1,37 +0,0 @@ -# glean activity - -Report user activity and feedback. Subcommands: report, feedback. - -```bash -glean activity [flags] -``` - -## Subcommands - -| Subcommand | Description | -|------------|-------------| -| `feedback` | Submit feedback on search results | -| `report` | Report a user activity event | - -## Flags - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--dry-run` | boolean | false | | -| `--json` | string | | JSON request body (required) **(required)** | - -## Examples - -```bash -glean activity report --json '{"events":[{"action":"VIEW","url":"https://example.com"}]}' -``` - -## Discovering Commands - -```bash -# Show machine-readable schema for this command -glean schema activity - -# List all available commands -glean schema | jq '.commands' -``` diff --git a/skills/glean-cli/reference/agents.md b/skills/glean-cli/reference/agents.md deleted file mode 100644 index 4c3ffdd..0000000 --- a/skills/glean-cli/reference/agents.md +++ /dev/null @@ -1,41 +0,0 @@ -# glean agents - -Manage and run Glean agents. Subcommands: list, get, schemas, run. - -```bash -glean agents [flags] -``` - -## Subcommands - -| Subcommand | Description | -|------------|-------------| -| `get` | Get details of a specific agent | -| `list` | List all available agents | -| `run` | Run an agent | -| `schemas` | Get input/output schemas for an agent | - -## Flags - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--dry-run` | boolean | false | | -| `--json` | string | | JSON request body | -| `--output` | json \| ndjson \| text | json | | - -## Examples - -```bash -glean agents list | jq '.[].id' -glean agents run --json '{"agentId":"my-agent","input":{"query":"test"}}' -``` - -## Discovering Commands - -```bash -# Show machine-readable schema for this command -glean schema agents - -# List all available commands -glean schema | jq '.commands' -``` diff --git a/skills/glean-cli/reference/announcements.md b/skills/glean-cli/reference/announcements.md deleted file mode 100644 index bb25a67..0000000 --- a/skills/glean-cli/reference/announcements.md +++ /dev/null @@ -1,39 +0,0 @@ -# glean announcements - -Manage Glean announcements. Subcommands: create, update, delete. - -```bash -glean announcements [flags] -``` - -## Subcommands - -| Subcommand | Description | -|------------|-------------| -| `create` | Create a new announcement | -| `delete` | Delete an announcement | -| `update` | Update an existing announcement | - -## Flags - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--dry-run` | boolean | false | | -| `--json` | string | | JSON request body (required) **(required)** | -| `--output` | json \| ndjson \| text | json | | - -## Examples - -```bash -glean announcements create --json '{"title":"Company Update","body":"..."}' -``` - -## Discovering Commands - -```bash -# Show machine-readable schema for this command -glean schema announcements - -# List all available commands -glean schema | jq '.commands' -``` diff --git a/skills/glean-cli/reference/answers.md b/skills/glean-cli/reference/answers.md deleted file mode 100644 index cc11587..0000000 --- a/skills/glean-cli/reference/answers.md +++ /dev/null @@ -1,41 +0,0 @@ -# glean answers - -Manage Glean answers. Subcommands: list, get, create, update, delete. - -```bash -glean answers [flags] -``` - -## Subcommands - -| Subcommand | Description | -|------------|-------------| -| `create` | Create a new answer | -| `delete` | Delete an answer | -| `get` | Get a specific answer | -| `list` | List all curated answers | -| `update` | Update an existing answer | - -## Flags - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--dry-run` | boolean | false | | -| `--json` | string | | JSON request body | -| `--output` | json \| ndjson \| text | json | | - -## Examples - -```bash -glean answers list | jq '.[].id' -``` - -## Discovering Commands - -```bash -# Show machine-readable schema for this command -glean schema answers - -# List all available commands -glean schema | jq '.commands' -``` diff --git a/skills/glean-cli/reference/api.md b/skills/glean-cli/reference/api.md deleted file mode 100644 index 250913a..0000000 --- a/skills/glean-cli/reference/api.md +++ /dev/null @@ -1,35 +0,0 @@ -# glean api - -Make a raw authenticated HTTP request to any Glean REST API endpoint. - -```bash -glean api [flags] -``` - -## Flags - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--dry-run` | boolean | false | Same as --preview | -| `--input` | string | | Path to a JSON file to use as request body | -| `--method` | GET \| POST \| PUT \| DELETE \| PATCH | GET | HTTP method | -| `--no-color` | boolean | false | Disable colorized output | -| `--preview` | boolean | false | Print request details without sending | -| `--raw` | boolean | false | Print raw response without syntax highlighting | -| `--raw-field` | string | | JSON request body as a string | - -## Examples - -```bash -glean api search --method POST --raw-field '{"query":"test"}' --no-color | jq .results -``` - -## Discovering Commands - -```bash -# Show machine-readable schema for this command -glean schema api - -# List all available commands -glean schema | jq '.commands' -``` diff --git a/skills/glean-cli/reference/chat.md b/skills/glean-cli/reference/chat.md deleted file mode 100644 index 5c092dc..0000000 --- a/skills/glean-cli/reference/chat.md +++ /dev/null @@ -1,34 +0,0 @@ -# glean chat - -Have a conversation with Glean AI. Streams response to stdout. - -```bash -glean chat [flags] -``` - -## Flags - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--dry-run` | boolean | false | Print request body without sending | -| `--json` | string | | Complete JSON chat request body (overrides individual flags) | -| `--message` | string | | Chat message (positional arg) **(required)** | -| `--save` | boolean | true | Save the chat session | -| `--timeout` | integer | 30000 | Request timeout in milliseconds | - -## Examples - -```bash -glean chat "What are the company holidays?" -glean chat --json '{"messages":[{"author":"USER","messageType":"CONTENT","fragments":[{"text":"What is Glean?"}]}]}' -``` - -## Discovering Commands - -```bash -# Show machine-readable schema for this command -glean schema chat - -# List all available commands -glean schema | jq '.commands' -``` diff --git a/skills/glean-cli/reference/collections.md b/skills/glean-cli/reference/collections.md deleted file mode 100644 index f41c6f8..0000000 --- a/skills/glean-cli/reference/collections.md +++ /dev/null @@ -1,43 +0,0 @@ -# glean collections - -Manage Glean collections. Subcommands: create, delete, update, add-items, delete-item. - -```bash -glean collections [flags] -``` - -## Subcommands - -| Subcommand | Description | -|------------|-------------| -| `add-items` | Add documents to a collection | -| `create` | Create a new collection | -| `delete` | Delete a collection | -| `delete-item` | Remove a document from a collection | -| `get` | Get a specific collection | -| `list` | List all collections | -| `update` | Update a collection | - -## Flags - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--dry-run` | boolean | false | | -| `--json` | string | | JSON request body | -| `--output` | json \| ndjson \| text | json | | - -## Examples - -```bash -glean collections create --json '{"name":"My Collection"}' -``` - -## Discovering Commands - -```bash -# Show machine-readable schema for this command -glean schema collections - -# List all available commands -glean schema | jq '.commands' -``` diff --git a/skills/glean-cli/reference/documents.md b/skills/glean-cli/reference/documents.md deleted file mode 100644 index d0a2e0e..0000000 --- a/skills/glean-cli/reference/documents.md +++ /dev/null @@ -1,40 +0,0 @@ -# glean documents - -Retrieve and summarize Glean documents. Subcommands: get, get-by-facets, get-permissions, summarize. - -```bash -glean documents [flags] -``` - -## Subcommands - -| Subcommand | Description | -|------------|-------------| -| `get` | Retrieve document metadata by URL or ID | -| `get-by-facets` | Retrieve documents matching facet filters | -| `get-permissions` | Inspect who has access to a document | -| `summarize` | Generate an AI summary of a document | - -## Flags - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--dry-run` | boolean | false | | -| `--json` | string | | JSON request body | -| `--output` | json \| ndjson \| text | json | | - -## Examples - -```bash -glean documents summarize --json '{"documentId":"DOC_ID"}' | jq .summary -``` - -## Discovering Commands - -```bash -# Show machine-readable schema for this command -glean schema documents - -# List all available commands -glean schema | jq '.commands' -``` diff --git a/skills/glean-cli/reference/entities.md b/skills/glean-cli/reference/entities.md deleted file mode 100644 index 0d759c8..0000000 --- a/skills/glean-cli/reference/entities.md +++ /dev/null @@ -1,37 +0,0 @@ -# glean entities - -List and read Glean entities and people. Subcommands: list, read-people. - -```bash -glean entities [flags] -``` - -## Subcommands - -| Subcommand | Description | -|------------|-------------| -| `list` | List entities by type and query | -| `read-people` | Get detailed people profiles | - -## Flags - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--json` | string | | JSON request body **(required)** | -| `--output` | json \| ndjson \| text | json | | - -## Examples - -```bash -glean entities read-people --json '{"query":"smith"}' | jq '.[].name' -``` - -## Discovering Commands - -```bash -# Show machine-readable schema for this command -glean schema entities - -# List all available commands -glean schema | jq '.commands' -``` diff --git a/skills/glean-cli/reference/insights.md b/skills/glean-cli/reference/insights.md deleted file mode 100644 index d2fac9a..0000000 --- a/skills/glean-cli/reference/insights.md +++ /dev/null @@ -1,37 +0,0 @@ -# glean insights - -Retrieve Glean usage insights. Subcommands: get. - -```bash -glean insights [flags] -``` - -## Subcommands - -| Subcommand | Description | -|------------|-------------| -| `get` | Get analytics data | - -## Flags - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--dry-run` | boolean | false | | -| `--json` | string | | JSON request body (required) **(required)** | -| `--output` | json \| ndjson \| text | json | | - -## Examples - -```bash -glean insights get --json '{"insightTypes":["SEARCH"]}' | jq . -``` - -## Discovering Commands - -```bash -# Show machine-readable schema for this command -glean schema insights - -# List all available commands -glean schema | jq '.commands' -``` diff --git a/skills/glean-cli/reference/messages.md b/skills/glean-cli/reference/messages.md deleted file mode 100644 index c92e144..0000000 --- a/skills/glean-cli/reference/messages.md +++ /dev/null @@ -1,36 +0,0 @@ -# glean messages - -Retrieve Glean messages. Subcommands: get. - -```bash -glean messages [flags] -``` - -## Subcommands - -| Subcommand | Description | -|------------|-------------| -| `get` | Retrieve a specific message | - -## Flags - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--json` | string | | JSON request body (required) **(required)** | -| `--output` | json \| ndjson \| text | json | | - -## Examples - -```bash -glean messages get --json '{"messageId":"MSG_ID"}' | jq . -``` - -## Discovering Commands - -```bash -# Show machine-readable schema for this command -glean schema messages - -# List all available commands -glean schema | jq '.commands' -``` diff --git a/skills/glean-cli/reference/pins.md b/skills/glean-cli/reference/pins.md deleted file mode 100644 index 65dd1f5..0000000 --- a/skills/glean-cli/reference/pins.md +++ /dev/null @@ -1,41 +0,0 @@ -# glean pins - -Manage Glean pins. Subcommands: list, get, create, update, remove. - -```bash -glean pins [flags] -``` - -## Subcommands - -| Subcommand | Description | -|------------|-------------| -| `create` | Create a new pin | -| `get` | Get a specific pin | -| `list` | List all pins | -| `remove` | Remove a pin | -| `update` | Update a pin | - -## Flags - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--dry-run` | boolean | false | | -| `--json` | string | | JSON request body | -| `--output` | json \| ndjson \| text | json | | - -## Examples - -```bash -glean pins list | jq '.[].id' -``` - -## Discovering Commands - -```bash -# Show machine-readable schema for this command -glean schema pins - -# List all available commands -glean schema | jq '.commands' -``` diff --git a/skills/glean-cli/reference/search.md b/skills/glean-cli/reference/search.md deleted file mode 100644 index d3a85cf..0000000 --- a/skills/glean-cli/reference/search.md +++ /dev/null @@ -1,46 +0,0 @@ -# glean search - -Search for content in your Glean instance. Results are JSON. - -```bash -glean search [flags] -``` - -## Flags - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--datasource` | []string | | Filter by datasource (repeatable) | -| `--disable-query-autocorrect` | boolean | false | Disable automatic query corrections | -| `--disable-spellcheck` | boolean | false | Disable spellcheck | -| `--dry-run` | boolean | false | Print request body without sending | -| `--facet-bucket-size` | integer | 10 | Maximum facet buckets per result | -| `--fetch-all-datasource-counts` | boolean | false | Return counts for all datasources | -| `--json` | string | | Complete JSON request body (overrides individual flags) | -| `--max-snippet-size` | integer | 0 | Maximum snippet size in characters | -| `--output` | json \| ndjson \| text | json | Output format | -| `--page-size` | integer | 10 | Number of results per page | -| `--query` | string | | Search query (positional arg) **(required)** | -| `--query-overrides-facet-filters` | boolean | false | Allow query operators to override facet filters | -| `--response-hints` | []string | [RESULTS QUERY_METADATA] | Response hints | -| `--return-llm-content` | boolean | false | Return expanded LLM-friendly content | -| `--tab` | []string | | Filter by result tab IDs (repeatable) | -| `--timeout` | integer | 30000 | Request timeout in milliseconds | -| `--type` | []string | | Filter by document type (repeatable) | - -## Examples - -```bash -glean search "vacation policy" | jq '.results[].document.title' -glean search --json '{"query":"Q1 reports","pageSize":5,"datasources":["confluence"]}' | jq . -``` - -## Discovering Commands - -```bash -# Show machine-readable schema for this command -glean schema search - -# List all available commands -glean schema | jq '.commands' -``` diff --git a/skills/glean-cli/reference/shortcuts.md b/skills/glean-cli/reference/shortcuts.md deleted file mode 100644 index e690a85..0000000 --- a/skills/glean-cli/reference/shortcuts.md +++ /dev/null @@ -1,42 +0,0 @@ -# glean shortcuts - -Manage Glean shortcuts (go-links). Subcommands: list, get, create, update, delete. - -```bash -glean shortcuts [flags] -``` - -## Subcommands - -| Subcommand | Description | -|------------|-------------| -| `create` | Create a new shortcut | -| `delete` | Delete a shortcut | -| `get` | Get a specific shortcut | -| `list` | List all shortcuts | -| `update` | Update an existing shortcut | - -## Flags - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--dry-run` | boolean | false | Print request without sending | -| `--json` | string | | JSON request body (see Glean API docs for shape) | -| `--output` | json \| ndjson \| text | json | | - -## Examples - -```bash -glean shortcuts list | jq '.results[].inputAlias' -glean shortcuts create --json '{"data":{"inputAlias":"test/link","destinationUrl":"https://example.com"}}' -``` - -## Discovering Commands - -```bash -# Show machine-readable schema for this command -glean schema shortcuts - -# List all available commands -glean schema | jq '.commands' -``` diff --git a/skills/glean-cli/reference/tools.md b/skills/glean-cli/reference/tools.md deleted file mode 100644 index 1ec167b..0000000 --- a/skills/glean-cli/reference/tools.md +++ /dev/null @@ -1,38 +0,0 @@ -# glean tools - -List and run Glean tools. Subcommands: list, run. - -```bash -glean tools [flags] -``` - -## Subcommands - -| Subcommand | Description | -|------------|-------------| -| `list` | List available platform tools | -| `run` | Execute a platform tool | - -## Flags - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--dry-run` | boolean | false | | -| `--json` | string | | JSON request body | -| `--output` | json \| ndjson \| text | json | | - -## Examples - -```bash -glean tools list | jq '.[].name' -``` - -## Discovering Commands - -```bash -# Show machine-readable schema for this command -glean schema tools - -# List all available commands -glean schema | jq '.commands' -``` diff --git a/skills/glean-cli/reference/verification.md b/skills/glean-cli/reference/verification.md deleted file mode 100644 index e6d51b3..0000000 --- a/skills/glean-cli/reference/verification.md +++ /dev/null @@ -1,39 +0,0 @@ -# glean verification - -Manage document verification. Subcommands: list, verify, remind. - -```bash -glean verification [flags] -``` - -## Subcommands - -| Subcommand | Description | -|------------|-------------| -| `list` | List documents pending verification | -| `remind` | Send a verification reminder | -| `verify` | Mark a document as verified | - -## Flags - -| Flag | Type | Default | Description | -|------|------|---------|-------------| -| `--dry-run` | boolean | false | | -| `--json` | string | | JSON request body | -| `--output` | json \| ndjson \| text | json | | - -## Examples - -```bash -glean verification list | jq '.[].document.title' -``` - -## Discovering Commands - -```bash -# Show machine-readable schema for this command -glean schema verification - -# List all available commands -glean schema | jq '.commands' -```