design/warp

4 min czytania 937 słów
design/warp screenshot

Warp: Terminal na nowo

„Wierzymy, że terminal jest jednym z najpotężniejszych narzędzi, jakie kiedykolwiek stworzono, ale jest też jednym z najbardziej onieśmielających." — Zach Lloyd, CEO Warp

Warp to nowoczesny terminal, który łączy surową moc CLI z użytecznością współczesnych aplikacji. Dowodzi, że narzędzia dla programistów nie muszą poświęcać znajomości na rzecz innowacji.


Dlaczego Warp ma znaczenie

Warp wziął najczcigodniejsze narzędzie programisty — terminal — i przemyślał je na nowo dla współczesnej ery, nie porzucając tego, co czyniło go potężnym.

Kluczowe osiągnięcia: - Architektura blokowa, która traktuje polecenia jako obiekty pierwszej klasy - Integracja AI, która wydaje się natywna, a nie doklejona - Nowoczesne doświadczenie edycji (zaznaczanie, cofanie, wiele kursorów) - Funkcje współpracy (Warp Drive, współdzielone przepływy pracy) - Zbudowany w Rust dla wydajności bez kompromisów w funkcjonalności


Kluczowe wnioski

  1. Blokowe wyjście przekształca chaos w obiekty - Traktowanie każdego polecenia+wyjścia jako dyskretnej, zaznaczalnej jednostki umożliwia kopiowanie, udostępnianie, nawigację i kontekst AI, czego ciągłe strumienie tekstu nie mogą zapewnić
  2. Wejście zakotwiczone na dole odzwierciedla znajomość czatu - Ustalona pozycja wejścia eliminuje obciążenie poznawcze związane z szukaniem promptu; użytkownicy zawsze wiedzą, gdzie pisać
  3. Integracja AI musi być opt-in i przejrzysta - Pokazuj rzeczywiste wygenerowane polecenie, oferuj tryb wyjaśniania i pozwalaj odrzucić każdą sugestię AI jednym klawiszem
  4. Addytywna innowacja zachowuje moc - Dodawaj nowoczesne udogodnienia bez usuwania możliwości; eksperci mogą ignorować nowe funkcje, podczas gdy nowicjusze z nich korzystają
  5. Narzędzia programistyczne mogą być kolaboracyjne - Współdzielone bloki i przepływy pracy dowodzą, że nawet tradycyjnie solowe narzędzia zyskują na funkcjach społecznościowych

Główna filozofia projektowania

Problem mostu

Terminale stoją przed unikalnym wyzwaniem: muszą służyć zarówno ekspertom, którzy używają ich od dziesięcioleci, JAK I nowicjuszom, którzy uważają je za onieśmielające. Rozwiązanie Warp jest addytywne — dodaje nowoczesne udogodnienia bez usuwania mocy.

TRADYCYJNY TERMINAL
┌─────────────────────────────────────────────────────────────┐
│ $ git status                                                │
│ On branch main                                              │
│ Your branch is up to date with 'origin/main'.              │
│                                                             │
│ Changes not staged for commit:                              │
│   (use "git add <file>..." to update what will be...)      │
│   modified: src/app.py                                      │
│                                                             │
│ $ _                                                         │
│                                                             │
│ (wszystko jest niezróżnicowanym tekstem)                    │
└─────────────────────────────────────────────────────────────┘

PODEJŚCIE WARP
┌─────────────────────────────────────────────────────────────┐
│  ┌─ Blok 1 ──────────────────────────────────────────────┐  │
│  │ $ git status                            [^] [Kopiuj]  │  │
│  ├───────────────────────────────────────────────────────┤  │
│  │ On branch main                                        │  │
│  │ Your branch is up to date with 'origin/main'.        │  │
│  │                                                       │  │
│  │ Changes not staged for commit:                        │  │
│  │   modified: src/app.py                               │  │
│  └───────────────────────────────────────────────────────┘  │
│                                                             │
│  ┌─ Wejście ─────────────────────────────────────────────┐  │
│  │ Wpisz polecenie...                       [AI] [Cmd+P] │  │
│  └───────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘

Kluczowy wniosek: Każde polecenie+wyjście to zaznaczalny, współdzielony blok

Biblioteka wzorców

1. Architektura blokowego wyjścia

Najbardziej znaczącą innowacją Warp jest traktowanie każdego polecenia i jego wyjścia jako dyskretnego „bloku" zamiast ciągłego tekstu.

Co czyni bloki potężnymi:

Funkcja Tradycyjne Bloki Warp
Zaznaczanie Tylko znak/linia Całe wyjście jako jednostka
Kopiowanie Ręczne zaznaczanie Kopiowanie jednym kliknięciem
Udostępnianie Zrzut ekranu lub wklejenie Link do bloku
Nawigacja Przewijanie tekstu Skakanie między blokami
Kontekst AI Brak Blok jest oknem kontekstu

Wzorzec implementacji:

// Struktura danych bloku
const Block = {
  id: 'block-uuid',
  command: 'git status',
  timestamp: Date.now(),
  output: {
    text: '...',
    exitCode: 0,
    duration: 234, // ms
  },
  metadata: {
    cwd: '/Users/dev/project',
    env: { /* snapshot */ },
  }
};

// Interakcje z blokiem
const BlockActions = {
  copy: (block) => copyToClipboard(block.output.text),
  share: (block) => generateShareableLink(block),
  rerun: (block) => executeCommand(block.command, block.metadata.cwd),
  edit: (block) => openCommandEditor(block.command),
};

Wizualne traktowanie:

/* Stylowanie kontenera bloku */
.block {
  --block-bg: var(--surface-secondary);
  --block-border: 1px solid var(--border-subtle);
  --block-radius: 8px;

  background: var(--block-bg);
  border: var(--block-border);
  border-radius: var(--block-radius);
  margin-bottom: 12px;

  /* Hover ujawnia akcje */
  &:hover .block-actions {
    opacity: 1;
  }
}

.block-command {
  font-family: var(--font-mono);
  font-size: 14px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border-subtle);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.block-output {
  padding: 12px;
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.5;
  white-space: pre-wrap;
}

.block-actions {
  opacity: 0;
  transition: opacity 150ms ease;
  display: flex;
  gap: 4px;
}

2. Wejście zakotwiczone na dole

W przeciwieństwie do tradycyjnych terminali, gdzie wejście pojawia się w linii z wyjściem, Warp zakotwicza obszar wejścia na dole, podobnie jak aplikacje czatowe.

Dlaczego to działa:

TRADYCYJNE (Wejście podąża za wyjściem)
┌────────────────────────────────────────┐
│ linia wyjścia 1                        │
│ linia wyjścia 2                        │
│ linia wyjścia 3                        │
│ $ _  ← Wejście przesuwa się z wyjściem │
│                                        │
│                                        │
│                                        │
└────────────────────────────────────────┘

WARP (Ustalona pozycja wejścia)
┌────────────────────────────────────────┐
│ linia wyjścia 1                        │
│ linia wyjścia 2                        │
│ linia wyjścia 3                        │
│                                        │
├────────────────────────────────────────┤
│ $ _  ← Wejście zawsze tutaj (spójne)   │
└────────────────────────────────────────┘

Korzyści dla modelu mentalnego: - Przewidywalne: Wejście jest zawsze w tym samym miejscu - Znajome: Odzwierciedla interfejsy czatowe (Wiadomości, Slack) - Efektywne: Bez przewijania w poszukiwaniu promptu - Przestronne: Pełnofunkcyjny edytor z obsługą wielu linii

Implementacja:

.terminal-layout {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

.output-area {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
}

.input-area {
  flex-shrink: 0;
  border-top: 1px solid var(--border-primary);
  padding: 12px 16px;
  background: var(--surface-primary);

  /* Nowoczesne wrażenie edytora tekstu */
  min-height: 48px;
  max-height: 200px; /* Rozszerzalny dla wielu linii */
}

3. Wzorce integracji AI

Funkcje AI Warp pokazują, jak zintegrować AI z narzędziem dla zaawansowanych użytkowników bez tworzenia wrażenia kuli u nogi.

Trzy tryby asystenta AI:

1. WEJŚCIE W JĘZYKU NATURALNYM
┌────────────────────────────────────────────────────────────┐
│ „znajdź wszystkie pliki pythona zmodyfikowane w           │
│   ostatnim tygodniu"                                       │
│                                                            │
│ ↓ AI tłumaczy na:                                          │
│                                                            │
│ find . -name "*.py" -mtime -7                             │
│                                                            │
│ [Uruchom] [Edytuj] [Wyjaśnij]                              │
└────────────────────────────────────────────────────────────┘

2. AKTYWNE AI (Kontekstowe sugestie)
┌────────────────────────────────────────────────────────────┐
│ $ git push origin main                                     │
│ error: failed to push some refs                           │
│                                                            │
│ ┌─ Sugestia AI ───────────────────────────────────────┐   │
│ │ 💡 Twoja gałąź jest w tyle. Spróbuj:                │   │
│ │    git pull --rebase origin main                    │   │
│ │                                      [Zastosuj] [×] │   │
│ └─────────────────────────────────────────────────────┘   │
└────────────────────────────────────────────────────────────┘

3. TRYB WYJAŚNIANIA (Edukacja)
┌────────────────────────────────────────────────────────────┐
│ $ tar -xzvf archive.tar.gz                                │
│                           [Wyjaśnij to polecenie]          │
│                                                            │
│ ┌─ Wyjaśnienie ───────────────────────────────────────┐   │
│ │ tar: Narzędzie archiwizacyjne                       │   │
│ │  -x: Wypakuj pliki                                  │   │
│ │  -z: Dekompresuj gzipem                             │   │
│ │  -v: Szczegółowo (pokaż pliki)                      │   │
│ │  -f: Określ nazwę pliku                             │   │
│ └─────────────────────────────────────────────────────┘   │
└────────────────────────────────────────────────────────────┘

Kluczowe decyzje projektowe:

  1. Opt-in, nie opt-out: Sugestie AI pojawiają się kontekstowo, ale nie przerywają przepływu
  2. Przejrzyste tłumaczenie: Gdy AI generuje polecenie, pokaż rzeczywiste polecenie
  3. Edukacyjne: Tryb wyjaśniania uczy użytkowników zamiast tworzyć zależność
  4. Odrzucalne: Każdy element AI może być zignorowany jednym klawiszem

4. Wzorzec palety poleceń

Warp implementuje nowoczesną paletę poleceń (Cmd+P), która udostępnia funkcje bez zapamiętywania skrótów.

┌────────────────────────────────────────────────────────────────────┐
│  Szukaj poleceń, ustawień, przepływów pracy...                     │
├────────────────────────────────────────────────────────────────────┤
│  Ostatnie                                                          │
│  ├─ Podziel panel w prawo                            Cmd+D         │
│  ├─ Przełącz sugestie AI                         Cmd+Shift+A       │
│  └─ Otwórz ustawienia                                Cmd+,         │
│                                                                    │
│  Polecenia                                                         │
│  ├─ Nowa karta                                       Cmd+T         │
│  ├─ Zamknij kartę                                    Cmd+W         │
│  ├─ Przejdź do bloku...                              Cmd+G         │
│  └─ Udostępnij blok                              Cmd+Shift+S       │
│                                                                    │
│  Przepływy pracy                                                   │
│  ├─ Wdróż na produkcję                                             │
│  ├─ Uruchom zestaw testów                                          │
│  └─ Zaktualizuj zależności                                         │
└────────────────────────────────────────────────────────────────────┘

Zasady projektowania:

  • Rozmyte wyszukiwanie: „podz pan" pasuje do „Podziel panel"
  • Pokazuj skróty: Ucz użytkowników podczas wyszukiwania
  • Ostatnie elementy najpierw: Spersonalizowane według wzorców użycia
  • Skategoryzowane: Grupuj powiązane polecenia

5. Przepływy pracy: Współdzielone sekwencje poleceń

Funkcja Workflows Warp pozwala użytkownikom zapisywać i udostępniać sekwencje poleceń, łącząc skrypty i zakładki.

# Przykładowy przepływ pracy: Wdrożenie na produkcję
name: "Wdróż na produkcję"
description: "Uruchom testy, zbuduj i wdróż"
author: "@team"
steps:
  - command: "npm test"
    description: "Uruchom zestaw testów"
  - command: "npm run build"
    description: "Zbuduj dla produkcji"
  - command: "git push origin main"
    description: "Wypchnij, aby uruchomić wdrożenie"

Traktowanie UI:

┌─ Przepływ pracy: Wdróż na produkcję ─────────────────────────────┐
│                                                                  │
│  Krok 1 z 3                                                      │
│  ┌─────────────────────────────────────────────────────────────┐ │
│  │ $ npm test                                                  │ │
│  │                                                             │ │
│  │ Uruchom zestaw testów                                       │ │
│  └─────────────────────────────────────────────────────────────┘ │
│                                                                  │
│  [Uruchom] [Pomiń] [Anuluj przepływ]              (*) ( ) ( )    │
└──────────────────────────────────────────────────────────────────┘

System projektowania wizualnego

System kolorów

:root {
  /* Ciemny motyw (domyślny) */
  --bg-primary: #0D0D0D;
  --bg-secondary: #1A1A1A;
  --bg-tertiary: #262626;

  --text-primary: #FFFFFF;
  --text-secondary: #A3A3A3;
  --text-muted: #737373;

  --border-subtle: rgba(255, 255, 255, 0.08);
  --border-primary: rgba(255, 255, 255, 0.12);

  /* Kolory semantyczne */
  --color-success: #22C55E;
  --color-error: #EF4444;
  --color-warning: #F59E0B;
  --color-info: #3B82F6;

  /* Akcent AI */
  --color-ai: #A855F7;  /* Fioletowy dla funkcji AI */

  /* Zaznaczenie i fokus */
  --color-selection: rgba(59, 130, 246, 0.3);
  --color-focus: #3B82F6;
}

Typografia

:root {
  /* Monospace dla wyjścia terminala */
  --font-mono: 'JetBrains Mono', 'Fira Code', 'SF Mono', monospace;

  /* Sans-serif dla elementów UI */
  --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

  /* Rozmiary */
  --text-xs: 11px;
  --text-sm: 13px;
  --text-base: 14px;
  --text-lg: 16px;

  /* Wysokości linii zoptymalizowane dla kodu */
  --line-height-tight: 1.3;
  --line-height-normal: 1.5;
  --line-height-relaxed: 1.7;
}

/* Wyjście terminala */
.terminal-text {
  font-family: var(--font-mono);
  font-size: var(--text-base);
  line-height: var(--line-height-normal);
  font-variant-ligatures: contextual;
  font-feature-settings: 'calt' 1;  /* Włącz ligatury */
}

/* Elementy UI */
.ui-text {
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: 500;
}

Wzorce animacji

Pojawienie się bloku

@keyframes block-enter {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.block {
  animation: block-enter 150ms ease-out;
}

Ujawnienie sugestii AI

@keyframes suggestion-reveal {
  from {
    opacity: 0;
    transform: translateY(8px);
    max-height: 0;
  }
  to {
    opacity: 1;
    transform: translateY(0);
    max-height: 200px;
  }
}

.ai-suggestion {
  animation: suggestion-reveal 200ms ease-out;
}

.ai-suggestion.dismissing {
  animation: suggestion-reveal 150ms ease-in reverse;
}

Stany ładowania

/* Wskaźnik strumieniowego wyjścia */
.block.executing::after {
  content: '';
  display: inline-block;
  width: 8px;
  height: 16px;
  background: var(--color-focus);
  animation: cursor-blink 1s step-end infinite;
}

@keyframes cursor-blink {
  50% { opacity: 0; }
}

/* Wskaźnik myślenia AI */
.ai-thinking {
  display: flex;
  gap: 4px;
}

.ai-thinking span {
  width: 6px;
  height: 6px;
  background: var(--color-ai);
  border-radius: 50%;
  animation: thinking-pulse 1.4s infinite ease-in-out both;
}

.ai-thinking span:nth-child(1) { animation-delay: 0s; }
.ai-thinking span:nth-child(2) { animation-delay: 0.16s; }
.ai-thinking span:nth-child(3) { animation-delay: 0.32s; }

@keyframes thinking-pulse {
  0%, 80%, 100% { transform: scale(0.6); opacity: 0.5; }
  40% { transform: scale(1); opacity: 1; }
}

Lekcje dla naszej pracy

1. Addytywna innowacja

Dodawaj nowoczesne funkcje bez usuwania mocy. Eksperci mogą ignorować nowe funkcje; nowicjusze z nich korzystają.

2. Strukturyzuj chaos

Architektura blokowa przekształca niezróżnicowany tekst w manipulowalne obiekty. Szukaj okazji do dodania struktury do nieustrukturyzowanej treści.

3. Stałe kotwice UI

Ustalona pozycja wejścia zmniejsza obciążenie poznawcze. Użytkownicy nie szukają, gdzie pisać.

4. AI jako asystent, nie zamiennik

Pokazuj rzeczywiste polecenie, nie tylko wynik. Tryb wyjaśniania uczy, zamiast tworzyć zależność.

5. Kolaboracyjne CLI

Współdzielone bloki i przepływy pracy dowodzą, że nawet tradycyjnie solowe narzędzia mogą mieć funkcje społecznościowe.


Często zadawane pytania

Czym jest architektura blokowa Warp?

Zamiast traktować wyjście terminala jako ciągły przewijany tekst, Warp strukturyzuje każde polecenie i jego wyjście jako dyskretny „blok". Każdy blok to zaznaczalna, kopiowalna, współdzielna jednostka z metadanymi (znacznik czasu, kod wyjścia, czas trwania). Umożliwia to kopiowanie jednym kliknięciem, udostępnianie linków, skakanie między poleceniami i dostarczanie AI skoncentrowanych okien kontekstu.

Dlaczego Warp umieszcza wejście na dole zamiast w linii?

Tradycyjne terminale umieszczają kursor wejścia w linii z wyjściem, co oznacza, że przesuwa się on wraz z rośnięciem wyjścia. Warp zakotwicza obszar wejścia na dole (jak aplikacje czatowe), zapewniając przewidywalną lokalizację, która eliminuje obciążenie poznawcze związane ze znajdowaniem miejsca do pisania. Umożliwia to również pełnofunkcyjny edytor wieloliniowy z nowoczesnymi możliwościami edycji.

Jak Warp integruje AI bez tworzenia zależności?

AI Warp działa w trzech trybach: tłumaczenie języka naturalnego (pokazując rzeczywiste wygenerowane polecenie), kontekstowe sugestie (opt-in i odrzucalne) oraz tryb wyjaśniania (uczący, co robią polecenia). Kluczową zasadą jest przejrzystość — AI zawsze pokazuje, co generuje, więc użytkownicy uczą się zamiast polegać.

Czym są Warp Workflows?

Workflows to współdzielne sekwencje poleceń zapisane w formacie YAML. Łączą lukę między jednorazowymi poleceniami a pełnymi skryptami, pozwalając zespołom dzielić się typowymi procedurami (jak kroki wdrożenia) z opisami dla każdego kroku. Workflows można odkrywać przez paletę poleceń i wykonywać krok po kroku.

Dlaczego Warp wybrał Rust do implementacji?

Rust zapewnia bezpieczeństwo pamięci i wydajność bez pauz garbage collectora, co jest krytyczne dla terminala, gdzie opóźnienia mają znaczenie. Umożliwia również architekturę Warp traktującą bloki jako ustrukturyzowane dane z bogatymi metadanymi, przy zachowaniu responsywności, jakiej użytkownicy oczekują od natywnych aplikacji.