Tree


.gitignorecommits | blame
Cargo.lockcommits | blame
Cargo.tomlcommits | blame
LICENSE-APACHEcommits | blame
LICENSE-MITcommits | blame
README.mdcommits | blame
alpaci/
alpacu/
src/
tests/

README.md

# alpaca

Unix native interface for interacting with LLMs.

`alpaca` is a fork of [`cogni`](https://github.com/leoshimo/cogni) by
[leoshimo](https://github.com/leoshimo) that utilizes
[Ollama Cloud](https://docs.ollama.com/cloud) rather than OpenAI.

## Focus

`alpaca` brings language model scripting (prompting) into familiar Unix
environment by focusing on:

- Ergonomics and accessibility in Unix shell
- Composability and interop with other programs - including `alpaca` itself
- Ease of language model programming in both ad-hoc and repeatable manner

For example, designing for IO redirection (`stdin`, `stdout`) allows `alpaca` to
work with files, editor buffers, clipboards, syslogs, sockets, and many external
tools without bespoke integrations.

## Features

- Unix-minded Design (IO redirection, composability, interop)
- Ad-hoc Language Model Scripting
- Flexible input and output formats (Text, JSON, NDJSON, Transcript)
- Standalone binary - No Python required
- Repeatable Scripts via Templates

## Non-Features

- Interactive use - instead, invoke `alpaca` from within interactive environments (REPLs, emacs, etc) 

## Installation

```sh
$ cargo install --path .
```

## Setup

`alpaca` talks to the [Ollama Cloud API](https://docs.ollama.com/cloud). It
expects an Ollama API Key (create one at
<https://ollama.com/settings/keys>) supplied via the `--apikey` option or more
conveniently the `OLLAMA_API_KEY` environment variable:

```sh
# in shell configuration
export OLLAMA_API_KEY=your-api-key
```

By default requests are sent to `https://ollama.com`. To target a different
host, for example a local Ollama server, set `OLLAMA_API_ENDPOINT`:

```sh
export OLLAMA_API_ENDPOINT=http://localhost:11434
```

Pick a model with `-m/--model` (default `gpt-oss:120b`). See
<https://ollama.com/library> for available model identifiers.

---

## Extra tools

### alpacu

`alpacu` is a small Go program in the `alpacu/` directory. It calls the Ollama
Cloud usage endpoint and prints your session quota (5 hour window) and weekly
quota (7 day window) as colored bars, with a countdown to the next reset and a
per-model request table with request counts.

It shares the same `OLLAMA_API_KEY` setup as `alpaca`. The key can also be
passed with `-k`. Build and install with make (Go 1.26, no dependencies):

```sh
$ cd alpacu
$ make                # build ./alpacu
$ make vet            # vet
$ sudo make install   # installs alpacu(1) and alpacu.1 to /usr/local
```

Options:

- `-k key`: API key. Falls back to `OLLAMA_API_KEY`
- `-b url`: base URL. Defaults to `$OLLAMA_API_ENDPOINT`, then `https://ollama.com`
- `-j`: print the raw JSON response instead of the rendered output
- `-h`: show help

See `alpacu.1` for the full man page.

### alpaci

`alpaci` edits prompt in `$VISUAL`, `$EDITOR`, or `vim`, sends saved text
to Ollama `POST /api/chat`, then writes reply to stdout. Piped stdin
prefills prompt. Editor uses `/dev/tty`, keeping editor I/O out of pipeline.

Uses `OLLAMA_API_KEY` or `-k`. Build needs Go 1.26:

```sh
$ cd alpaci
$ make                # build ./alpaci
$ make vet            # vet
$ sudo make install   # installs alpaci(1) and alpaci.1 to /usr/local
```

```sh
# Write a prompt in the editor, send it, see the reply
$ alpaci

# Pick a model and reasoning effort
$ alpaci -m gpt-oss:120b -e high

# Set a system prompt
$ alpaci -s "Answer in one sentence"

# Edit piped input in the editor before sending
$ git diff --staged | alpaci -s "Write a conventional commit message"

# Sit in the middle of a pipeline: pipe in, edit, pipe out
$ curl -s "wttr.in/?1" | alpaci -s "Summarize this weather in 1 sentence" | say
```

Options:

- `-m model`: model to use. Defaults to `$ALPACA_MODEL`, then `glm-5.3-flash`
- `-e effort`: reasoning effort, one of `low`, `medium`, `high`, `none`. Defaults to `$ALPACA_EFFORT`, then `low`. With `none`, the request omits the think field
- `-s system`: system prompt
- `-T secs`: request timeout in seconds. Defaults to 300
- `-k key`: API key. Falls back to `OLLAMA_API_KEY`
- `-b url`: base URL. Defaults to `$OLLAMA_API_ENDPOINT`, then `https://ollama.com`
- `-j`: print the raw JSON response instead of the reply
- `-h`: show help

`$VISUAL` and `$EDITOR` split on whitespace; no quote or escape parsing.
Use wrapper script for complex editor command. `-s` sends system message before
user prompt. Temporary file is removed. `-T` must be positive.

Each successful request is saved as a readable, length-prefixed transcript in
`$XDG_DATA_HOME/alpaca/` (or `~/.local/share/alpaca/`). Run `alpaci c` to
continue the newest transcript: its final assistant reply opens in the editor,
and each saved follow-up is sent with the entire conversation as context. The
saved model, effort and system prompt are reused unless explicitly overridden.
Save an empty editor buffer to leave the continuation loop.

See `alpaci.1`.

---

## Basic Usage

See `alpaca --help` for documentation

```sh
# Via stdin
$ echo "What is 50 + 50?" | alpaca
50 + 50 equals 100.

# Via file
$ echo "What is 50 + 50?" > input.txt
$ alpaca input.txt
50 + 50 equals 100.

# Via flags
#  -s, --system <MSG>            Sets system prompt (Always first)
#  -a, --assistant <MSG>         Appends assistant message
#  -u, --user <MSG>              Appends user message
$ alpaca --system "Solve the following math problem" --user "50 + 50"
50 + 50 equals 100.

# Via repetitions of same flags. Useful for few-shot prompting
$ alpaca --system "Solve the following math problem" \
    -u "1 + 1" \
    -a "2" \
    -u "22 + 20" \
    -a "42" \
    -u "50 + 50"
100

# Via both flags and stdin. Flag messages come before stdin / file
$ echo "50 + 50" | alpaca --system "Solve the following math problem" \
    -u "1 + 1" \
    -a "2" \
    -u "22 + 20" \
    -a "42"
100
```

---

## Tour of alpaca

An gallery of examples to get the inspiration flowing

> :warning: `alpaca` uses the [Ollama Cloud API](https://docs.ollama.com/cloud), thus *any data fed into program will be sent to their servers* (unless you point `OLLAMA_API_ENDPOINT` at a local server).

### In the Shell

```sh
# Creating Summary of Meeting Transcripts
$ cat meeting_saved_chat.txt \
    | alpaca -s "Extract the links mentioned in this transcript, and provide a high level summary of the discussion points"

# Narrate Weather Summary
$ curl -s "wttr.in/?1" \
    | alpaca -s "Summarize today's weather using the output. Respond in 1 short sentence." \
    | say

# Create a ffmpeg cheatsheet from man page
$ man ffmpeg \
    | alpaca -T 300 -s "Create a cheatsheet given a man page. Output should be in Markdown, and should be a set of example usages under headings." \
    > cheatsheet.md

# Create a commit message for staged changes
$ git diff --staged \
    | alpaca -s "Create a commit message for the given staged changes. Use conventional commit format. Answer in a single-line raw plaintext. Don't use markdown." \
    | git commit -F -
```

### In Emacs

Emacs can use `shell-command-on-region` to pipe buffer regions to `alpaca`.

For example, the following defines a command that plumbs region to `alpaca`, optionally replacing original contents:

```emacs-lisp
(defun leoshimo/alpaca-on-region (start end prompt replace)
  "Run alpaca on region. Prefix arg means replace region, instead of separate output buffer"
  (interactive "r\nsPrompt: \nP")
  (shell-command-on-region start end
                           (format "alpaca -s \"%s\"" prompt)
                           nil replace))

(global-set-key (kbd "M-c") #'leoshimo/alpaca-on-region)
```

This binding is useful across a wide range of tasks, for example:

- Normalizing non-uniform text, such as unstructured logs to structured JSON events.
- Editing or organizing text semantically, such as rewording or grouping by category.
- Generating summary for an Org Agenda doc.

### In Vim

Vim can run external shell commands on entire buffer or visual selection to
power similar workflows possible from Emacs. See `h :!` in vim.

For example, a bulleted list of fruits can be sorted by color by:

1. Selecting the list of fruits in visual mode
2. Type `:!alpaca -s "Sort this list by color"`