- 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
397 lines
10 KiB
Markdown
397 lines
10 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
cortex <TAB>
|
|
# add children decay export graph index journal link list query remove serve show update
|
|
```
|
|
|
|
### 13.2 Option Completion
|
|
|
|
```bash
|
|
cortex add --<TAB>
|
|
# --title --content --tags --status --section --help
|
|
```
|
|
|
|
### 13.3 Node ID Completion
|
|
|
|
```bash
|
|
cortex show <TAB>
|
|
# abc123 def456 ghi789 (recent node IDs)
|
|
|
|
cortex show abc<TAB>
|
|
# abc123 abc456 (matching prefixes)
|
|
```
|
|
|
|
### 13.4 Tag Completion
|
|
|
|
```bash
|
|
cortex list --tags <TAB>
|
|
# auth backend security api docs (existing tags)
|
|
```
|
|
|
|
### 13.5 Kind/Status Completion
|
|
|
|
```bash
|
|
cortex add <TAB>
|
|
# memory component task decision
|
|
|
|
cortex list --status <TAB>
|
|
# active todo done deprecated
|
|
```
|
|
|
|
### 13.6 Graph Completion
|
|
|
|
```bash
|
|
cortex use <TAB>
|
|
# default work personal myproject
|
|
```
|
|
|
|
## Implementation
|
|
|
|
### Completion Generator
|
|
|
|
```typescript
|
|
// 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```zsh
|
|
#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
|
|
|
|
```fish
|
|
# 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
|
|
|
|
```powershell
|
|
# 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
|
|
|
|
```typescript
|
|
// 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
|
|
```bash
|
|
cortex completions bash > /etc/bash_completion.d/cortex
|
|
# or
|
|
cortex completions bash >> ~/.bashrc
|
|
```
|
|
|
|
### Zsh
|
|
```bash
|
|
cortex completions zsh > ~/.zsh/completions/_cortex
|
|
# Add to ~/.zshrc: fpath=(~/.zsh/completions $fpath)
|
|
```
|
|
|
|
### Fish
|
|
```bash
|
|
cortex completions fish > ~/.config/fish/completions/cortex.fish
|
|
```
|
|
|
|
### PowerShell
|
|
```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
|
|
|
|
- [Bash Programmable Completion](https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html)
|
|
- [Zsh Completion System](https://zsh.sourceforge.io/Doc/Release/Completion-System.html)
|
|
- [Fish Completions](https://fishshell.com/docs/current/completions.html)
|
|
- [PowerShell Tab Completion](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/register-argumentcompleter)
|