Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 7 additions & 12 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run cargo fmt
uses: actions-rs/cargo@v1
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This action is deprecated, unmaintained for like 6 years
https://github.com/actions-rs/cargo

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need this at all? The GH runners should have all of the rust toolchain already installed

- uses: dtolnay/rust-toolchain@1.85
with:
command: fmt
args: -p warp-command-signatures -p warp-completion-metadata
components: rustfmt, clippy
- name: Run cargo fmt
run: cargo fmt -p warp-command-signatures -p warp-completion-metadata --check
- name: Run cargo clippy
uses: actions-rs/cargo@v1
with:
command: clippy
args: -p warp-command-signatures -p warp-completion-metadata --all-targets --all-features -- -D warnings
run: cargo clippy -p warp-command-signatures -p warp-completion-metadata --all-targets --all-features -- -D warnings
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@1.85
- name: Run tests
uses: actions-rs/cargo@v1
with:
command: test
args: --verbose
run: cargo test --verbose
101 changes: 101 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# AGENTS.md

This file provides guidance to WARP (warp.dev) when working with code in this repository.

## Overview

This repository provides command completion signatures ("specs") for Warp terminal. It contains two Rust crates:

- **`warp-command-signatures`**: The main library that embeds and exposes command specs. Used as a dependency by `warp-internal`.
- **`warp-completion-metadata`**: Core types for signatures, arguments, options, generators, and the Fig-compatible JSON schema.

## Build and Test Commands

```bash
# Build
cargo build

# Run tests
cargo test --verbose

# Lint (fmt + clippy)
cargo fmt -p warp-command-signatures -p warp-completion-metadata
cargo clippy -p warp-command-signatures -p warp-completion-metadata --all-targets --all-features -- -D warnings

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would consider ommitting this or turning it into a skill.

The reason is:

  1. Building and testing is pretty obvious for the LLM in this repo, there's no reason it needs to get injected in every system prompt
  2. We probably don't want the LLM to eagerly run fmt and clippy

# Autogenerate PowerShell cmdlet specs (requires pwsh installed)
cargo run --bin autogenerate_powershell
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems potentially errorprone, the LLM isn't going to understand what autogenerate powershell even means. Again, seems like a good use case for a skill instead of the top level agents.Md

```

## Architecture

### Command Specs (JSON)

Specs are JSON files based on the [Fig completion spec schema](https://fig.io/docs/reference), but **Warp does not use Fig's JavaScript generators**. Instead:

- The `generatorName` field references Rust-based generators (see below)
- Fig's `generateSpec` JavaScript field is present in some imported specs but is **ignored** by Warp
- Static suggestions, templates (`filepaths`, `folders`), and subcommand/option definitions work as documented

| Location | Description |
|----------|-------------|
| `command-signatures/json/*.json` | Hand-written specs |
| `command-signatures/json/autogenerated/powershell/*.json` | Auto-generated PowerShell cmdlet specs |
| `command-signatures/json/overrides/powershell/*.json` | Hand-written overrides for autogenerated specs |

The `assets.rs` module uses `rust-embed` to flatten these directories into a single namespace at compile time, so callers just use `signature_by_name("git")`.

### Generators (Rust)

Generators produce dynamic completions by running shell commands. They are defined in `command-signatures/src/generators/` (one file per command or command family).

A generator consists of:
1. A `GeneratorProcess` (either a static `CommandBuilder` or a function that builds a command from tokens)
2. An `on_complete_callback` that parses the command output into `Suggestion`s

JSON specs reference generators via the `generatorName` field (e.g. `"generatorName": "branches"`). The mapping from name → Rust code is established in `generators/mod.rs` via `dynamic_command_signature_data()`.

Example from `brew.rs`:
```rust
CommandSignatureGenerators::new("brew")
.add_generator(
"formulae_generator", // Referenced in JSON as "generatorName": "formulae_generator"
Generator::script(CommandBuilder::single_command("brew list -1"), |output| {
output.trim().lines()
.map(|line| Suggestion::with_description(line, "Installed formula"))
.collect_unordered_results()
}),
)
```

### Override System

For autogenerated specs (currently PowerShell only), hand-written augmentations live in `json/overrides/`. Overrides are matched by option name or argument index and merged at generation time. Only `template` and `generatorName` fields are currently supported for overrides.

## Adding a New Command Spec
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels like a skill. I think the AGENTs.MD should be pretty high level and explain the semantics of what our completion system is and how it's inspired by Fig but a lot of the other things in this file (how to create a spec, examples, etc) can go in a skills.

The main advantage is the LLM can take advantage of progressive disclosure so it only reads this information in as needed


1. **JSON spec**: Create `command-signatures/json/<command>.json` following the Fig schema
2. **Generator** (if needed): Add a new file in `command-signatures/src/generators/`, define a `generator()` function returning `CommandSignatureGenerators`, and register it in `generators/mod.rs`

**Style guideline**: Match the formatting conventions used in the command's `--help` output. For example, if the help text uses `UPPER_CASE` for positional argument names, use the same casing in the spec's argument `name` field.

### Recommended Examples

When creating new specs, use these as reference:

- **Simple spec with generator**: `json/kill.json` + `src/generators/kill.rs` — minimal example showing `generatorName` usage for process and signal completions
- **Complex spec with multiple generators**: `json/brew.json` + `src/generators/brew.rs` — shows subcommands, options, and multiple generators (`formulae_generator`, `services`, etc.)

## Key Types

- `Signature`: Defines a command/subcommand (name, options, arguments, subcommands)
- `Argument`: A positional parameter with types (Template, Generator, or literal Suggestion)
- `Opt`: A flag/option with optional arguments
- `Generator`: Produces dynamic suggestions by running shell commands
- `Template`: Built-in generators for files/folders

## Testing Invariants

Tests in `lib.rs` verify:
- All `GeneratorName`s referenced in specs exist in `dynamic_command_signature_data()`
- All JSON specs deserialize without error
- Generator commands contain no unsafe (unquoted) newlines (required for TMUX control mode)
4 changes: 2 additions & 2 deletions completion-metadata/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ pub enum Shell {
/// A shell that can assume POSIX-compliant syntax.
Posix,
Powershell,
CmdExe
CmdExe,
}

impl Shell {
Expand All @@ -262,7 +262,7 @@ impl Shell {
match self {
Shell::Posix => "2>/dev/null",
Shell::Powershell => "2> $null",
Shell::CmdExe => "2> NUL"
Shell::CmdExe => "2> NUL",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cargo fmt fixed this

}
}
}
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[toolchain]
channel = "1.82"
channel = "1.85"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we use 1.92 in warp-internal, why 1.85 here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are new clippy lints in 1.92 which causes linting to fail. I updated to 1.85 b/c it's recent enough to fix the CI error but before these new lints. I do agree we should upgrade but I wanted to avoid scope-creeping this PR too much.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sgtm, makes sense

components = ["rustfmt", "clippy"]
targets = ["aarch64-apple-darwin", "x86_64-apple-darwin"]
profile = "minimal"