Files
cortex/docs/milestones/13-shell-completions.md
omigamedev d484f61b29 Add development plan with 13 milestone specifications
- docs/plan.md: Master roadmap with phases and priorities
- docs/milestones/01-13: Detailed specs for each feature
- Updated CLAUDE.md with plan references and build commands

Milestones cover:
- Phase 1: Temporal versioning, auto-capture, context injection, codebase indexing
- Phase 2: Daily journal, content ingestion, graph visualization, import/export
- Phase 3: Multi-graph, smart retrieval, TUI dashboard, browser extension, shell completions
2026-02-03 09:36:08 +01:00

10 KiB

Milestone 13: Shell Completions

Overview

Auto-completion for Cortex CLI in Bash, Zsh, Fish, and PowerShell. Tab-complete commands, node IDs, tags, and options.

Motivation

  • Tab completion is expected in modern CLIs
  • Reduces typing and errors
  • Helps discoverability of commands
  • Professional polish

Features

13.1 Command Completion

cortex <TAB>
# add  children  decay  export  graph  index  journal  link  list  query  remove  serve  show  update

13.2 Option Completion

cortex add --<TAB>
# --title  --content  --tags  --status  --section  --help

13.3 Node ID Completion

cortex show <TAB>
# abc123  def456  ghi789  (recent node IDs)

cortex show abc<TAB>
# abc123  abc456  (matching prefixes)

13.4 Tag Completion

cortex list --tags <TAB>
# auth  backend  security  api  docs  (existing tags)

13.5 Kind/Status Completion

cortex add <TAB>
# memory  component  task  decision

cortex list --status <TAB>
# active  todo  done  deprecated

13.6 Graph Completion

cortex use <TAB>
# default  work  personal  myproject

Implementation

Completion Generator

// src/cli/completions/index.ts
export function generateCompletions(shell: 'bash' | 'zsh' | 'fish' | 'powershell'): string {
  switch (shell) {
    case 'bash':
      return generateBashCompletions();
    case 'zsh':
      return generateZshCompletions();
    case 'fish':
      return generateFishCompletions();
    case 'powershell':
      return generatePowerShellCompletions();
  }
}

Bash Completions

# Generated by cortex completions bash
_cortex_completions() {
  local cur prev words cword
  _init_completion || return

  local commands="add children decay export graph index journal link list query remove serve show update use graphs"
  local kinds="memory component task decision"
  local statuses="active todo doing done deprecated"

  case "${prev}" in
    cortex)
      COMPREPLY=($(compgen -W "${commands}" -- "${cur}"))
      return 0
      ;;
    add)
      COMPREPLY=($(compgen -W "${kinds}" -- "${cur}"))
      return 0
      ;;
    --kind)
      COMPREPLY=($(compgen -W "${kinds}" -- "${cur}"))
      return 0
      ;;
    --status)
      COMPREPLY=($(compgen -W "${statuses}" -- "${cur}"))
      return 0
      ;;
    --tags)
      # Dynamic: fetch existing tags
      local tags=$(cortex --get-tags 2>/dev/null)
      COMPREPLY=($(compgen -W "${tags}" -- "${cur}"))
      return 0
      ;;
    show|update|remove|link|children)
      # Dynamic: fetch node IDs
      local nodes=$(cortex --get-nodes "${cur}" 2>/dev/null)
      COMPREPLY=($(compgen -W "${nodes}" -- "${cur}"))
      return 0
      ;;
    use)
      # Dynamic: fetch graphs
      local graphs=$(cortex --get-graphs 2>/dev/null)
      COMPREPLY=($(compgen -W "${graphs}" -- "${cur}"))
      return 0
      ;;
  esac

  # Options
  if [[ "${cur}" == -* ]]; then
    local opts="--help --version --title --content --tags --status --kind --limit --format"
    COMPREPLY=($(compgen -W "${opts}" -- "${cur}"))
    return 0
  fi
}

complete -F _cortex_completions cortex

Zsh Completions

#compdef cortex

_cortex() {
  local -a commands
  commands=(
    'add:Add a node to the knowledge graph'
    'query:Search the knowledge graph'
    'show:Show a node and its connections'
    'list:List nodes'
    'update:Update a node'
    'remove:Remove a node'
    'link:Create a link between nodes'
    'graph:Visualize the knowledge graph'
    'children:List child nodes'
    'journal:Daily journal'
    'index:Index project'
    'serve:Start web server'
    'decay:Mark old nodes as stale'
    'use:Switch active graph'
    'graphs:Manage graphs'
  )

  local -a kinds=(memory component task decision)
  local -a statuses=(active todo doing done deprecated)

  _arguments -C \
    '1:command:->command' \
    '*::arg:->args'

  case "$state" in
    command)
      _describe -t commands 'cortex commands' commands
      ;;
    args)
      case "$words[1]" in
        add)
          _arguments \
            '1:kind:(memory component task decision)' \
            '--title[Node title]:title:' \
            '--content[Node content]:content:' \
            '--tags[Tags]:tags:->tags' \
            '--status[Status]:status:(active todo doing done deprecated)'
          ;;
        show|update|remove|children)
          _arguments '1:node:->nodes'
          ;;
        link)
          _arguments \
            '1:from:->nodes' \
            '2:to:->nodes' \
            '--type[Edge type]:type:(depends_on contains implements blocked_by subtask_of relates_to supersedes about)'
          ;;
        list)
          _arguments \
            '--kind[Filter by kind]:kind:(memory component task decision)' \
            '--status[Filter by status]:status:(active todo doing done deprecated)' \
            '--tags[Filter by tags]:tags:->tags'
          ;;
        use)
          _arguments '1:graph:->graphs'
          ;;
      esac
      ;;
  esac

  case "$state" in
    nodes)
      local -a nodes
      nodes=(${(f)"$(cortex --get-nodes 2>/dev/null)"})
      _describe -t nodes 'nodes' nodes
      ;;
    tags)
      local -a tags
      tags=(${(f)"$(cortex --get-tags 2>/dev/null)"})
      _describe -t tags 'tags' tags
      ;;
    graphs)
      local -a graphs
      graphs=(${(f)"$(cortex --get-graphs 2>/dev/null)"})
      _describe -t graphs 'graphs' graphs
      ;;
  esac
}

_cortex

Fish Completions

# cortex.fish
complete -c cortex -f

# Commands
complete -c cortex -n __fish_use_subcommand -a add -d 'Add a node'
complete -c cortex -n __fish_use_subcommand -a query -d 'Search'
complete -c cortex -n __fish_use_subcommand -a show -d 'Show node'
complete -c cortex -n __fish_use_subcommand -a list -d 'List nodes'
complete -c cortex -n __fish_use_subcommand -a update -d 'Update node'
complete -c cortex -n __fish_use_subcommand -a remove -d 'Remove node'
complete -c cortex -n __fish_use_subcommand -a link -d 'Link nodes'
complete -c cortex -n __fish_use_subcommand -a graph -d 'Visualize graph'

# Kinds
complete -c cortex -n '__fish_seen_subcommand_from add' -a 'memory component task decision'

# Dynamic node completion
complete -c cortex -n '__fish_seen_subcommand_from show update remove' -a '(cortex --get-nodes)'

# Tags
complete -c cortex -n '__fish_seen_subcommand_from list' -l tags -a '(cortex --get-tags)'

PowerShell Completions

# cortex.ps1
Register-ArgumentCompleter -Native -CommandName cortex -ScriptBlock {
  param($wordToComplete, $commandAst, $cursorPosition)

  $commands = @('add', 'query', 'show', 'list', 'update', 'remove', 'link', 'graph', 'children', 'journal', 'index', 'serve', 'decay', 'use', 'graphs')
  $kinds = @('memory', 'component', 'task', 'decision')
  $statuses = @('active', 'todo', 'doing', 'done', 'deprecated')

  $elements = $commandAst.CommandElements
  $command = $elements[1].Value

  if ($elements.Count -eq 2) {
    $commands | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
      [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
    }
  }
  elseif ($command -eq 'add' -and $elements.Count -eq 3) {
    $kinds | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
      [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
    }
  }
  elseif ($command -in @('show', 'update', 'remove')) {
    $nodes = cortex --get-nodes $wordToComplete 2>$null
    $nodes -split "`n" | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
      [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
    }
  }
}

CLI Support Commands

// Hidden commands for completion scripts
program
  .command('--get-nodes [prefix]', { hidden: true })
  .action(async (prefix) => {
    const nodes = await listNodes({ limit: 20 });
    const filtered = prefix
      ? nodes.filter(n => n.id.startsWith(prefix))
      : nodes;
    console.log(filtered.map(n => `${n.id.slice(0, 8)}\t${n.title}`).join('\n'));
  });

program
  .command('--get-tags', { hidden: true })
  .action(async () => {
    const tags = await getAllTags();
    console.log(tags.join('\n'));
  });

program
  .command('--get-graphs', { hidden: true })
  .action(async () => {
    const graphs = listGraphs();
    console.log(graphs.map(g => g.name).join('\n'));
  });

CLI Commands

Command Description
cortex completions bash Output bash completions
cortex completions zsh Output zsh completions
cortex completions fish Output fish completions
cortex completions powershell Output PowerShell completions
cortex completions install Auto-install for current shell

Installation Instructions

Bash

cortex completions bash > /etc/bash_completion.d/cortex
# or
cortex completions bash >> ~/.bashrc

Zsh

cortex completions zsh > ~/.zsh/completions/_cortex
# Add to ~/.zshrc: fpath=(~/.zsh/completions $fpath)

Fish

cortex completions fish > ~/.config/fish/completions/cortex.fish

PowerShell

cortex completions powershell >> $PROFILE

Testing

  • Bash completions work
  • Zsh completions work
  • Fish completions work
  • PowerShell completions work
  • Dynamic node ID completion
  • Dynamic tag completion
  • Install command works

Acceptance Criteria

  • All four shells supported
  • Commands and options complete
  • Node IDs complete dynamically
  • Tags complete dynamically
  • Easy installation command
  • No errors on missing cortex binary

Estimated Effort

  • Bash completions: 2 hours
  • Zsh completions: 3 hours
  • Fish completions: 2 hours
  • PowerShell completions: 2 hours
  • CLI support commands: 2 hours
  • Install command: 1 hour
  • Testing: 2 hours
  • Total: ~14 hours

Dependencies

  • None

References