One Shot AI
  • Go 79.6%
  • Nix 20.4%
Find a file
2026-05-12 20:30:15 +02:00
nix nix 2026-04-27 13:02:05 +02:00
.gitignore gitignore 2026-04-27 13:08:14 +02:00
alejandra.toml start 2026-04-27 12:42:27 +02:00
flake.lock start 2026-04-27 12:42:27 +02:00
flake.nix nix 2026-04-27 13:02:05 +02:00
go.mod works 2026-04-27 12:59:17 +02:00
go.sum works 2026-04-27 12:59:17 +02:00
main.go add default model config 2026-05-12 20:30:15 +02:00
README.md add default model config 2026-05-12 20:30:15 +02:00

osai

osai is "one shot ai": a small Go command-line utility for sending either a custom prompt or a named prompt script to an OpenAI-compatible chat completions endpoint.

It is designed around a simple XDG-based layout:

  • config lives at $XDG_CONFIG_HOME/osai/config.toml
  • prompt scripts live at $XDG_CONFIG_HOME/osai/prompts/*.sh

If you run osai <name>, osai looks for a script called $XDG_CONFIG_HOME/osai/prompts/<name>.sh. If it exists, the script is executed and its stdout becomes the final prompt. If no matching script exists, the CLI treats the remaining arguments as a custom prompt and sends them directly.

Features

  • simple CLI interface
  • OpenAI-compatible chat completions support via openai-go
  • XDG config discovery through os.UserConfigDir()
  • prompt scripts for reusable prompts
  • optional prompt script model hints
  • -m model override per invocation
  • Nix package output
  • Home Manager module for declarative installation and configuration

Requirements

  • an OpenAI-compatible API endpoint that supports POST /chat/completions
  • a valid API key for that endpoint
  • a model name accepted by that endpoint

For this project, the configured openai-endpoint should be the API base URL, for example:

  • https://api.openai.com/v1
  • https://chat.example.com/api
  • http://localhost:1234/v1

osai appends chat/completions through the client library.

Installation

Go

Build directly:

go build .

Run without installing:

go run . hello world

Nix

Build the package from this flake:

nix build .#default

The flake exports:

  • packages.x86_64-linux.default
  • packages.x86_64-linux.osai

Configuration

Create config.toml at:

$XDG_CONFIG_HOME/osai/config.toml

Example:

openai-endpoint = "https://api.openai.com/v1"
openai-key = "sk-..."
openai-default-model = "gpt-5.2"

Secret-file example:

openai-endpoint = "https://api.openai.com/v1"
openai-key-file = "/run/secrets/osai-openai-key"
openai-default-model = "gpt-5.2"

Fields:

  • openai-endpoint: base URL of the OpenAI-compatible API
  • openai-key: bearer token used for the request
  • openai-key-file: path to a file containing the bearer token
  • openai-default-model: default model used unless -m or a prompt script model hint is used

Exactly one of openai-key or openai-key-file must be set.

If openai-key-file is used, osai reads the file contents and trims surrounding whitespace. This makes it suitable for secret-management tools that write newline-terminated files, such as sops-nix.

Usage

Custom prompt

If no matching script exists, all remaining arguments are joined into a single prompt:

osai explain this shell pipeline

Equivalent prompt sent to the model:

explain this shell pipeline

Override the model

Use -m to override openai-default-model for a single call:

osai -m gpt-4.1 write a commit message for these changes

For named prompt scripts, -m also overrides any model hint in the script.

Named prompt script

If this file exists:

$XDG_CONFIG_HOME/osai/prompts/explain.sh

then:

osai explain

will execute that script and use its stdout as the prompt.

Additional CLI arguments are passed to the script:

osai explain main.go

Prompt scripts

Prompt scripts are plain executable files, typically shell scripts ending in .sh.

The script contract is intentionally small:

  • the script is executed directly
  • an optional # osai-model: <model> comment in the leading comment block selects the model for that script
  • stdout is captured
  • trimmed stdout becomes the final prompt
  • stderr is preserved for error reporting
  • a non-zero exit code causes osai to fail

Model selection precedence is:

  1. -m
  2. # osai-model: <model> in a named prompt script
  3. openai-default-model

Example script:

#!/usr/bin/env sh
# osai-model: qwen2.5-coder:32b

file="${1:-main.go}"

cat <<EOF
Explain the following file briefly and point out the most important behavior:

$file
EOF

Make it executable:

chmod +x "$XDG_CONFIG_HOME/osai/prompts/explain.sh"

Error handling

osai exits with a non-zero status and prints an error to stderr when:

  • the config file cannot be found or parsed
  • a required config field is missing
  • both openai-key and openai-key-file are set
  • openai-key-file cannot be read or is empty
  • the resolved prompt is empty
  • a prompt script fails or prints nothing
  • the API request fails
  • the API response contains no usable completion text

Endpoint compatibility note

osai uses github.com/openai/openai-go/v3. Some reverse proxies and Cloudflare setups block the default openai-go User-Agent and X-Stainless-* headers. This project strips those headers before sending requests because some OpenAI-compatible gateways reject them even when the same request succeeds with curl.

Home Manager module

This flake exports a Home Manager module under:

  • homeModules.default
  • homeModules.osai

The module provides:

  • programs.osai.enable
  • programs.osai.package
  • programs.osai.settings
  • programs.osai.scripts

When enabled, it:

  • installs the osai package
  • writes ~/.config/osai/config.toml
  • links the configured scripts into ~/.config/osai/prompts/

Home Manager example

{
  imports = [ inputs.osai.homeModules.default ];

  programs.osai = {
    enable = true;

    settings = {
      "openai-endpoint" = "https://chat.cumsek.com/api";
      "openai-key-file" = "/run/secrets/osai-openai-key";
      "openai-default-model" = "gpt-oss:20b";
    };

    scripts = [
      ./prompts/explain.sh
      ./prompts/commit-message.sh
    ];
  };
}

Home Manager option details

programs.osai.enable

Enables the package and XDG config generation.

programs.osai.package

Overrides the package to install. By default this uses the flake's own package:

self.packages.${pkgs.system}.default

programs.osai.settings

An attribute set rendered to TOML and written to osai/config.toml.

programs.osai.scripts

A list of Nix paths. Each path is linked into osai/prompts/ using its basename.

For example:

scripts = [
  ./prompts/explain.sh
  ./prompts/review.sh
];

produces:

  • ~/.config/osai/prompts/explain.sh
  • ~/.config/osai/prompts/review.sh

That means the CLI command uses the basename without the .sh suffix:

osai explain
osai review

Development

Enter the dev shell:

nix develop

Build with Go:

go build ./...

Run locally:

go run . hello

Repository layout

.
├── flake.nix
├── go.mod
├── go.sum
├── main.go
└── nix
    └── home-manager.nix

Current behavior summary

  1. Read config from the XDG config directory.
  2. Check whether the first CLI argument matches a prompt script.
  3. If it does, read any leading # osai-model: hint, execute the script, and capture stdout as the prompt.
  4. If it does not, join the CLI args into a custom prompt.
  5. Use -m, the script model hint, or the configured default model, in that order.
  6. Send the prompt to the configured OpenAI-compatible endpoint.
  7. Print the first completion message to stdout.