Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
25 changes: 22 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@

This package includes command line utilities that interacts with LiveKit. It allows you to:

- Bootstrap new applications from templates
- Create access tokens
- Access LiveKit APIs, create, delete rooms, etc.
- Access LiveKit APIs, create and delete rooms, etc.
- Join a room as a participant, inspecting in-room events
- Start and manage Egress
- Start and manage Egresses
- Perform load testing, efficiently simulating real-world load

# Installation
Expand Down Expand Up @@ -55,7 +56,7 @@ make install

# Usage

See `lk --help` for a complete list of subcommands.
See `lk --help` for a complete list of subcommands. The `--help` flag can also be used on any subcommand for more information.

## Set up your project (new)

Expand Down Expand Up @@ -86,6 +87,24 @@ lk project list
lk project set-default <project_name>
```

## Bootstrapping an application

The LiveKit CLI can help you bootstrap applications from a number of convenient template repositories, using your project credentials to set up required environment variables and other configuration automatically. To create an application from a template, run the following:

```shell
lk app create --template <template_name> my-app
```

Then follow the CLI prompts to finish your setup.

For a list of all available templates, run:

```shell
lk app list-templates
```

See the [LiveKit Templates Index](https://github.com/livekit-examples/index?tab=readme-ov-file) for details about templates, and for instructions on how to contribute your own.

## Publishing to a room

### Publish demo video track
Expand Down
36 changes: 35 additions & 1 deletion cmd/lk/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"fmt"
"os"
"regexp"
"strings"

"github.com/charmbracelet/huh"
"github.com/charmbracelet/huh/spinner"
Expand Down Expand Up @@ -78,6 +79,12 @@ var (
},
},
},
{
Name: "list-templates",
Usage: "List available templates to bootstrap a new application",
Flags: []cli.Flag{jsonFlag},
Action: listTemplates,
},
{
Hidden: true,
Name: "install",
Expand Down Expand Up @@ -175,6 +182,31 @@ func requireProject(ctx context.Context, cmd *cli.Command) error {
return err
}

func listTemplates(ctx context.Context, cmd *cli.Command) error {
templates, err := bootstrap.FetchTemplates(ctx)
if err != nil {
return err
}

if cmd.Bool("json") {
PrintJSON(templates)
} else {
const maxDescLength = 64
table := CreateTable().Headers("Template", "Description").BorderRow(true)
for _, t := range templates {
desc := strings.Join(wrapToLines(t.Desc, maxDescLength), "\n")
url := theme.Focused.Title.Render(t.URL)
tags := theme.Help.ShortDesc.Render("#" + strings.Join(t.Tags, " #"))
table.Row(
t.Name,
desc+"\n\n"+url+"\n"+tags,
)
}
fmt.Println(table)
}
return nil
}

func setupTemplate(ctx context.Context, cmd *cli.Command) error {
verbose := cmd.Bool("verbose")
install := cmd.Bool("install")
Expand Down Expand Up @@ -218,7 +250,9 @@ func setupTemplate(ctx context.Context, cmd *cli.Command) error {
WithTheme(theme)
var options []huh.Option[string]
for _, t := range templateOptions {
options = append(options, huh.NewOption(t.Name, t.URL))
descStyle := theme.Help.ShortDesc
optionText := t.Name + " " + descStyle.Render("#"+strings.Join(t.Tags, " #"))
options = append(options, huh.NewOption(optionText, t.URL))
}
templateSelect.(*huh.Select[string]).Options(options...)
preinstallPrompts = append(preinstallPrompts, templateSelect)
Expand Down
10 changes: 8 additions & 2 deletions cmd/lk/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,9 +262,15 @@ func listProjects(ctx context.Context, cmd *cli.Command) error {
return baseStyle
}
}).
Headers("Name", "URL", "API Key", "Default")
Headers("Name", "URL", "API Key")
for _, p := range cliConfig.Projects {
table.Row(p.Name, p.URL, p.APIKey, fmt.Sprint(p.Name == cliConfig.DefaultProject))
var pName string
if p.Name == cliConfig.DefaultProject {
pName = "* " + p.Name
} else {
pName = " " + p.Name
}
table.Row(pName, p.URL, p.APIKey)
}
fmt.Println(table)
}
Expand Down
32 changes: 32 additions & 0 deletions cmd/lk/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,38 @@ func wrapWith(wrap string) func(string) string {
}
}

func ellipsizeTo(str string, maxLength int) string {
if len(str) <= maxLength {
return str
}
ellipsis := "..."
contentLen := max(0, min(len(str), maxLength-len(ellipsis)))
return str[:contentLen] + ellipsis
}

func wrapToLines(input string, maxLineLength int) []string {
words := strings.Fields(input)
var lines []string
var currentLine strings.Builder

for _, word := range words {
if currentLine.Len()+len(word)+1 > maxLineLength {
lines = append(lines, currentLine.String())
currentLine.Reset()
}
if currentLine.Len() > 0 {
currentLine.WriteString(" ")
}
currentLine.WriteString(word)
}

if currentLine.Len() > 0 {
lines = append(lines, currentLine.String())
}

return lines
}

// Provides a temporary path, a function to relocate it to a permanent path,
// and a function to clean up the temporary path that should always be deferred
// in the case of a failure to relocate.
Expand Down
31 changes: 31 additions & 0 deletions cmd/lk/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,34 @@ func TestMapStrings(t *testing.T) {
t.Error("mapStrings should apply the function to all elements")
}
}

func TestEllipziseTo(t *testing.T) {
str := "This is some long string that should be ellipsized"
ellipsized := ellipsizeTo(str, 12)
if len(ellipsized) != 12 {
t.Error("ellipsizeTo should return a string of the specified length")
}
if ellipsized != "This is s..." {
t.Error("ellipsizeTo should ellipsize the string")
}
}

func TestWrapToLines(t *testing.T) {
str := "This is a long string that should be wrapped to multiple lines"
wrapped := wrapToLines(str, 10)
if len(wrapped) != 8 {
t.Error("wrapToLines should return a slice of lines")
}
if !slices.Equal([]string{
"This is a",
"long",
"string",
"that",
"should be",
"wrapped to",
"multiple",
"lines",
}, wrapped) {
t.Error("wrapToLines should wrap the string to the specified width")
}
}
17 changes: 9 additions & 8 deletions pkg/bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,15 @@ var templateIgnoreFiles = []string{
}

type Template struct {
Name string `yaml:"name" json:"name"`
Desc string `yaml:"desc" json:"description,omitempty"`
URL string `yaml:"url" json:"url,omitempty"`
Docs string `yaml:"docs" json:"docs_url,omitempty"`
Image string `yaml:"image" json:"image_ref,omitempty"`
Tags []string `yaml:"tags" json:"tags,omitempty"`
Requires []string `yaml:"requires" json:"requires,omitempty"`
IsSandbox bool `yaml:"is_sandbox" json:"is_sandbox,omitempty"`
Name string `yaml:"name" json:"name"`
Desc string `yaml:"desc" json:"description,omitempty"`
URL string `yaml:"url" json:"url,omitempty"`
Docs string `yaml:"docs" json:"docs_url,omitempty"`
Image string `yaml:"image" json:"image_ref,omitempty"`
Tags []string `yaml:"tags" json:"tags,omitempty"`
Attrs map[string]string `yaml:"attrs" json:"attrs,omitempty"`
Requires []string `yaml:"requires" json:"requires,omitempty"`
IsSandbox bool `yaml:"is_sandbox" json:"is_sandbox,omitempty"`
}

type SandboxDetails struct {
Expand Down
2 changes: 1 addition & 1 deletion version.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@
package livekitcli

const (
Version = "2.2.1"
Version = "2.3.0"
)
Loading