Von Terminals und Effizienz: Einblick in die Autokomplettierungsmagie von Fig.io und AWS CodeWhisperer

20.03.2024Ricky Elfner
DevOps CLI Developer Experience Productivity Development Integration Web Development Framework

Banner

Besonders in technischen Berufen ist die Kommandozeile vor allem für Entwickler nicht mehr wegzudenken. Dabei wird sie von Millionen Entwicklern täglich genutzt, um Code zu schreiben, zu kompilieren, auszuführen oder zu debuggen. Doch jeder, der das Terminal nutzt, weiß, wie viele unterschiedliche Befehle es gibt. Des Weiteren ist es oft unübersichtlich und meist auch nicht selbsterklärend. Um diese Probleme aus der Welt zu schaffen, hat sich Fig.io das Ziel gesetzt, vor allem durch Autocompletion Tippfehler zu verhindern und die korrekte Syntax bereitzustellen.

Aus diesem Grund bin ich auch auf fig.io gestoßen, als ich nach einer Möglichkeit gesucht habe, meinen alltäglichen Arbeitstag zu vereinfachen. Dies ist eine Möglichkeit, das grundlegende Erlebnis auf der Kommandozeile zu verbessern – dabei ist dies nicht nur für Anfänger nützlich, sondern auch für erfahrene Entwickler.

Im November 2023 war es dann aber so weit dass ein weiteres Unternehmen von Amazon übernommen wurde. Dabei wurde fig.io als Erweiterung ihres KI-gestützten Produktivitätswerkzeugs in CodeWhisperer integriert. Dadurch werden IDE-ähnliche Vervollständigungen für über 500 CLI-Anwendungen, einschließlich Git, npm, Docker und AWS CLI, sowie Inline-Dokumentation und Übersetzungen von natürlicher Sprache in Code zur Verfügung gestellt.

Doch in diesem Techup werde ich zu vorallem auf die Autocomplete-Funktionalität von fig eingehen, da dies mein eigentlicher Usecase war.

Installation

Bei der Installation habe ich mich zunächst einmal direkt an die Dokumentation von fig selbst gehalten. Doch hier kommt es nach dem Download über Homebrew zu Fehlern. Der Grund hierfür ist, dass fig heruntergeladen wird und dies alleine nicht mehr für neue User zur Verfügung steht. Aus diesem Grund musste die Installation direkt über Amazon gemacht werden. Für die Anmeldung ist eine Amazon BuilderID notwendig. Sobald die Anmeldung erfolgreich durchgeführt wurde, schauen wir uns zunächst die Funktionen an, welche Out-of-the-box zur Verfügung gestellt werden.

Grundfunktionen

Möchte man nun das Dashboard öffnen, kann dies mittels dem Command cw gemacht werden. Dort werden auch direkt die ersten Grundfunktionen Autocomplete und AI Translation angezeigt.

Ein häufig genutzter Anwendungsfall ist das Wechseln von Ordnern. Dabei wird direkt eine Vorschau der möglichen Ordner angezeigt.

Beispiel CD

Doch nicht nur in diesem Fall, sondern auch bei unterschiedlichen Syntaxbeispielen wie Git oder Docker.

example_git

Eine weitere Grundfunktion ist die AI Translation. Dabei hat man die Möglichkeit, anhand einer Beschreibung den entsprechenden Befehl zu bekommen. Hierfür führt man zunächst einmal den Befehl cw ai aus. Anschließend kann man als Text sein Vorhaben beschreiben.

In diesem Beispiel möchte ich alle Branches haben, die in diesem Git-Repository vorhanden sind. Nachdem der Shell-Befehl generiert wurde, hat man die Möglichkeit, diesen direkt auszuführen, ihn zu überarbeiten, die Antwort noch einmal neu zu generieren, eine andere Frage zu stellen oder alles abzubrechen.

Über das CodeWhisperer Dashboard, zugänglich durch den Befehl cw, lassen sich vielfältige Einstellungen vornehmen. Diese umfassen unter anderem Anpassungen des Autokomplettierungs-Verhaltens, Datenschutzeinstellungen, Integrationen mit anderen Tools, Anpassungen des Themes und der Darstellung. Das Dashboard bietet somit eine breite Palette an Personalisierungs- und Konfigurationsmöglichkeiten, um das Benutzererlebnis von fig individuell anzupassen und seine eigene Effizienz zu steigern.

Features

Ein besonders hilfreiches Feature ist das Erstellen von eigenen Autocompletion-Möglichkeiten. Dies erweist sich vor allem dann als nützlich, wenn man eigene Skripte verwenden möchte. In unserem Fall verfügen wir über verschiedene b-nova Skripte, die das Leben unserer Entwickler erleichtern sollen. Deshalb ist es sinnvoll, eine Autokomplettierung für alle Mitarbeiter bereitzustellen. Genau diese Funktionalität bietet fig.io.

Beginnen wir einfach und sehen uns an, wie dies genau funktioniert. Zunächst muss man das GitHub-Repository autocomplete von Fig auschecken oder forken. Ein direkter Tipp hierzu: Dies sollte idealerweise unter dem Pfad ~/.fig geschehen, damit die selbst erstellten Autokomplettierungs-Tasks auch funktionieren.

Individuelle Tasks

Sobald dies geschehen ist, öffne das Projekt, da wir noch alle notwendigen Abhängigkeiten installieren müssen:

1
npm install

Im Anschluss kann dann der erste eigene Task erstellt werden; im Kontext von Fig wird dies als “Completion Spec” bezeichnet. Das Grundgerüst kann automatisch erstellt werden. In unserem Beispiel werden wir dies “techup” nennen:

1
npm run create-spec techup

Damit wird folgendes techup File erstellt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
const completionSpec: Fig.Spec = {
  name: "techup",
  description: "",
  subcommands: [{
    name: "my_subcommand",
    description: "Example subcommand",
    subcommands: [{
      name: "my_nested_subcommand",
      description: "Nested subcommand, example usage: 'techup my_subcommand my_nested_subcommand'"
    }],
  }],
  options: [{
    name: ["--help", "-h"],
    description: "Show help for techup",
  }],
  // Only uncomment if techup takes an argument
  // args: {}
};
export default completionSpec;

Es ist wichtig, dass der Dateiname mit der name-Eigenschaft übereinstimmt, da Fig diesen verwendet, um die Completion-Spezifikation zu laden, wenn der Benutzer den Namen eingibt. Fig.Spec in der ersten Zeile ist ein TypeScript-Typ, der Fig mitteilt, dass wir eine Completion-Spezifikation definieren. Die Syntax export default am Ende stellt sicher, dass sie korrekt exportiert wird und somit kompiliert werden kann.

Möchte man seinen eigenen Task testen, kann dies mittels des dev-Modus gemacht werden.

1
npm run dev

Im Terminal bekommt man dann direkt seine Änderung angezeigt:

So funktioniert es: Ein Standardbeispiel detailliert erklärt

Um dieses Konstrukt besser zu verstehen gucken wir uns am besten einmal die Terminologie anhand eines git-Befehls an:

Da dies ein sehr gutes Beispiel ist, um den Aufbau besser zu verstehen, bauen wir nun diesen Task. Um dies Schritt für Schritt auszuführen, legen wir die Datei git.ts selbst an und definieren zunächst den Namen und eine Beschreibung:

1
2
3
4
5
6
const completionSpec: Fig.Spec = {
  name: "git",
  description: "The basic content tracker",
};

export default completionSpec;

Nun möchten wir als erstes Subcommand das auschecken eines bestimmten Branches haben:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const completionSpec: Fig.Spec = {
  name: "git",
  description: "The example content tracker",
  subcommands: [
    {
      name: "checkout",
      description: "Switch branches or restore working tree files",
    },
  ],
};

Nun möchten wir noch definieren, dass dieser Befehl den entsrpechenden Branch-Name entgegen nimmt. Dies wird mittels des Args-Attribut definiert:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
const completionSpec: Fig.Spec = {
  name: "git",
  description: "The example content tracker",
  subcommands: [
    {
      name: "checkout",
      description: "Switch branches or restore working tree files",
      args: {
        name: "branch",
        description: "the branch you want to checkout",
        isOptional: true,
      },
    },
  ],
};
export default completionSpec;

Wenn wir unser Bild für die Terminologie anschauen, gibt es noch die Möglichkeit einen neune Branch mit der Option -b zu erstellen. Dafür fügen wir nun noch das options-Attribut hinzu:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const completionSpec: Fig.Spec = {
  name: "git",
  description: "The example content tracker",
  subcommands: [
    {
      name: "checkout",
      description: "Switch branches or restore working tree files",
      args: {
        name: "branch",
        description: "the branch you want to checkout",
        isOptional: true,
      },
      options: [
        {
          name: ["-b"],
          description:
            "Create a new branch named <new_branch> and start it at <start_point>; 
          args: {
            name: "New Branch",
          },
        },,
      ],
    },
  ],
};
export default completionSpec;

Führt man dieses Script nun aus, bekommt man den enstprechenden Vorschlag.

Usecases

Wie bereits erwähnt, nutzen wir intern sehr viele Skripte. Diese werden alle als Alias angelegt. Aus diesem Grund haben wir uns unsere eigene Autocompletion für diese Fälle angelegt. Gibt man beispielsweise bnova ein, werden alle Skripte angezeigt, die in unserem Repository verfügbar sind. Deshalb wird das Attribut insertValue verwendet, damit es direkt in das Terminal eingefügt wird. Mit \b wird jeweils ein Zeichen aus der Eingabe gelöscht, und mit \n wird eine neue Zeile eingefügt, damit das Kommando direkt ausgeführt wird.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
    {
      name: "bnova",
      description: "use a b-nova alias",
      args: {
        name: "alias",
        description: "allias for b-nova",
        isOptional: true,
      },
      options: [
        {
          name: ["ch_cdtechup"],
          description: "Execute the command: ch_cdtechup",
          insertValue: "\b\b\b\b\b\b\b\b\bch_cdtechup\n",
        },
        {
          name: ["ch_cddashboard"],
          description: "Execute the command: ch_cddashboard",
          insertValue: "\b\b\b\b\b\b\b\b\bch_vib2bgkextensionsini\n",
        },

Eine weitere Möglichkeit ist es eigene Generatoren zu schreiben. Ein benutzerdefinierter Generator bei fig.io ermöglicht es, eine Funktion zu erstellen, die das tokenisierte Array der Benutzereingabe entgegennimmt, mehrere Shell-Befehle auf dem Rechner des Benutzers ausführt und dann Vorschläge zur Anzeige generiert. Dies bedeutet, dass du mit einem benutzerdefinierten Generator sowohl die Logik zur Verarbeitung der Benutzereingabe als auch die Ausführung relevanter Befehle und die Erstellung von Vorschlägen auf Basis der Ergebnisse dieser Befehle in einem Schritt abwickeln kannst.

Ein ganz Einfachs Beispiel dafür wäre dies:

1
2
3
4
5
6
const do_ls: Fig.Generator = {
  script: ["ls"],
  postProcess(out) {
    return out.split("\n").map((name) => ({ name }));
  },
};

Dies könnte dann in einem Subcommand genutzt werden:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
    {
      name: "test",
      description: "test",
      args: {
        name: "directory",
        description: "display the directory",
        isOptional: true,
     		generators: do_ls,
      },
      options: [
        {
          name: ["home"],
          description: "Jump to Home folder",
          insertValue: "\b\b\b\b\b\b\bcd ~/\n",
        },
      ],
    },

Es gibt jedoch auch Template Generatoren wie filepaths und folders die den Inhalt automatisch anzeigen in dem das Attribut template anstatt generators verwendet wird.

Um sich einen genauen Überblick zu machen, welche Attribute oder auch sonstige Funktionen es gibt, ist die Dokumentation von fig.io sehr zu empfehlen.

Integration von Fig Autocomplete

Natürlich ist es auch möglich, dass man die autocomplete Function von fig nicht nur im normalen Terminal verwendet, sondern auch in seiner IDEA. Die meiste Zeit verwende ich selbst IntelliJ von Jetbrains, da dies leider nicht out-of-the-box funktioniert hat musste ich zunächste die entsprechenden Integrations installieren. Dieser Befehl wird auch im Dashboard unter Intergrations angezeigt.

1
cw integrations install input-method

Nach dem die Installation abegeschlossen war, hätte eigentlich nur noch IntelliJ neugestartet werden müssen. Doch hier gab es einen Fehler das dieses Plugin nicht kompatibel ist:

Um dieses Problem zu beheben, muss stattdessen einfach das Amazon Plugin “AWS Toolkit” installiert werden. Nach einem weiteren Neustart ist dann auch in der IDEA die Funktionalität verfügbar:

AWS CodeWhisperer

Mit der zuvor geätigten Installation steht nun auch CodeWhisperer allgemein in deiner IDEA zur Verfügung. Da ich als mein Techup Theme eigentlich fig.io ausgewählt habe, gehe ich nur kurz auf CodeWhisperer ein.

Um CodeWhisperer zu nutzen muss man sich nur mit seiner AWS Builder anmelden. Amazon CodeWhisperer ist ein fortschrittlicher Code-Generator, der Entwickler dabei unterstützt, schneller und effizienter zu programmieren. Ein zentrales Merkmal von Amazon CodeWhisperer ist seine Fähigkeit, in Echtzeit präzise Codevorschläge zu generieren, die auf den eingegebenen Kommentaren und dem bereits bestehenden Code des Entwicklers basieren. Diese Vorschläge können von einzelnen Zeilen bis hin zu kompletten Codeblöcken reichen, was nicht nur die Entwicklungszeit verkürzt, sondern auch zu einer deutlichen Steigerung der Codequalität beiträgt. Dabei werden folgende Sprachen Unterstützt:

  • Java
  • Python
  • JavaScript
  • TypeScript
  • C#
  • Go
  • PHP
  • Rust
  • Kotlin
  • SQL
  • Ruby
  • C++
  • C
  • Shell
  • Scala
  • Infrastructure as Code (IaC) Sprachen mit dem meisten Support:
    • JSON (AWS CloudFormation)
    • YAML (AWS CloudFormation)
    • HCL (Terraform)
    • CDK (Typescript, Python)

Somit sieht man, dass Entwickler ihre bevorzugten Programmiersprachen und IDEs nutzen können um CodeWhisperer für spezifischere Empfehlungen anzupassen.

Darüber hinaus sieht Amazon auch einen wichtigen Bereich bei Security- und Compliance-Themen im Entwicklungsprozess. CodeWhisperer erkennt durch seinen Securityscan potenzieller Sicherheitslücken und trägt durch das Hervorheben von Codevorschlägen, die öffentlichem Code ähneln, aktiv zur Entwicklungssicherheit bei. Diese Funktionen ermöglichen es Entwicklern, bewusster und verantwortungsvoller mit dem Einsatz und der Integration von Codebestandteilen umzugehen, insbesondere im Hinblick auf Open-Source-Lizenzierungen.

Zusätzlich bietet die Integration des generativen KI-Assistenten Amazon Q eine tiefergehende Unterstützung durch Expertenberatung über einen intergrierten Chat, um Code zu erklären, zu transformieren und personalisierte Vorschläge für Tests, Debugging und Optimierungen zu erhalten.

Amazon bietet CodeWhisperer in zwei Tarifmodellen an: einer kostenlosen Version für Einzelentwickler und einer kostenpflichtigen Professional-Version für Unternehmen.

Abschließend ist festzuhalten, dass Amazon CodeWhisperer nicht nur die Produktivität der Entwickler durch beschleunigte Code-Erstellung steigert, sondern auch zu einer höheren Codequalität beiträgt.

Fazit

In meinem Techup habe ich deutlich gemacht, dass ich mich vor allem für fig.io interessiert habe, da ich in den angebotenen Features einen echten Mehrwert für unser Team gesehen habe. Nachdem ich mich jedoch eingehender mit dem Thema beschäftigt habe, musste ich feststellen, dass Features wie der Script-Builder, das Teilen von SSH-Credentials oder DotEnv-Files nun ausschließlich Bestandskunden von fig.io zur Verfügung stehen. Ich selbst, als Neukunde, konnte lediglich die Autocomplete-Funktion über CodeWhisperer nutzen.

Dennoch muss ich sagen, dass die Möglichkeit, seine Autocompletion-Scripts selbst zu schreiben, sehr ansprechend ist. Allerdings muss man auch sagen, dass dies, je nach Anzahl der eigenen Scripts, zunächst sehr zeitaufwendig sein kann. Ebenfalls muss berücksichtigt werden, dass zu Beginn ein erheblicher Lernaufwand notwendig ist, um alle verfügbaren Spec-Attribute zu verstehen und nachzuvollziehen, wie genau die eigenen Generatoren implementiert werden können.

Ricky Elfner

Ricky Elfner – Denker, Überlebenskünstler, Gadget-Sammler. Dabei ist er immer auf der Suche nach neuen Innovationen, sowie Tech News, um immer über aktuelle Themen schreiben zu können.