Project

askcii

0.0
The project is in a healthy, maintained state
A terminal-friendly interface for interacting with LLM models
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 5.25
~> 13.0
~> 3.0
~> 0.6

Runtime

= 1.5.1
~> 5.92
 Project Readme

askcii

Talk to an LLM from your shell — the Unix way.

askcii is a filter, not an application. It reads standard input, writes standard output, reports errors on standard error, and returns meaningful exit codes. It streams, it pipes, it scripts. It does not take over your terminal.

askcii 'explain the difference between fork and exec'
git diff --staged | askcii 'write a conventional commit message'
cat error.log | askcii --json 'summarize the failures' | jq -r .content

Supports Anthropic, OpenAI, Gemini, DeepSeek, Mistral, Perplexity, xAI, OpenRouter, and Ollama.

Install

gem install askcii

Then create a profile:

askcii config add work --provider anthropic --model claude-sonnet-5 \
  --key-env ANTHROPIC_API_KEY --default

Or run askcii config add work with no flags to be prompted, or askcii config edit to write the YAML by hand.

Why it composes

Most LLM CLIs are chat apps that happen to live in a terminal. askcii is built to be a link in a pipeline:

  • Streams by default, with $stdout unbuffered, so | tee and | less show text as it arrives instead of in 4KB gulps.
  • Dies quietly on SIGPIPE. askcii '…' | head -5 exits 141 with nothing on stderr, exactly like cat would.
  • Distinct exit codes, so askcii … || handle $? can tell a typo from an outage.
  • --json everywhere, so you never have to parse a human-readable table.
  • Nothing interactive is required. Every command is scriptable; the prompts are a convenience, not the interface.

Usage

askcii [options] <prompt>...        Ask a question (also reads stdin)
askcii <command> [options]
Command Purpose
ask Ask a question (the default)
config Manage provider profiles
sessions Inspect and prune conversation history
version Print the version

Ask options

Flag Meaning
-P, --profile NAME Use a named profile
-m, --model MODEL Override the profile's model
-s, --session NAME Continue a named conversation
-p, --private Write nothing to disk
-r, --last Print the last reply instead of asking
--no-stream Buffer the reply, print it once complete
--timeout SECS Abort the request after SECS seconds
-j, --json Machine-readable output
-v, --verbose Diagnostics on stderr

Standard input

If stdin is not a terminal it is read and placed before the prompt, separated by a blank line — no wrapper prose is added. If you give no prompt argument, stdin becomes the prompt.

echo 'what is 2+2' | askcii                  # stdin is the prompt
git diff | askcii 'review this'              # stdin is the context
askcii 'summarize' < report.txt              # same thing

Sessions

Without --session, each run is a one-shot: no prior context is replayed, and only the most recent exchange is kept so that -r still works. This is why your history does not fill with thousands of single-use conversations.

askcii 'quick question'        # one-shot, forgotten next time
askcii -r                      # still prints that reply

askcii -s refactor 'how should I split this module?'
askcii -s refactor 'show me the first step'   # remembers

askcii -p 'nothing about this is recorded'

Manage them:

askcii sessions list
askcii sessions show refactor
askcii sessions clear refactor
askcii sessions prune --older-than 30

Configuration

Profiles live in $XDG_CONFIG_HOME/askcii/config.yml (default ~/.config/askcii/config.yml), created with mode 0600:

default_profile: work
profiles:
  work:
    provider: anthropic
    model: claude-sonnet-5
    api_key_env: ANTHROPIC_API_KEY
  secure:
    provider: openai
    model: gpt-5.4
    api_key_command: op read op://private/openai/key
  local:
    provider: ollama
    model: llama3.2

It is a plain file — edit it, template it, check it into your dotfiles.

askcii config list          # '*' marks the default; shows where each key comes from
askcii config path
askcii config edit
askcii config default local

API keys

Resolved in order, first match winning:

  1. $ASKCII_API_KEY
  2. the profile's api_key_env (an environment variable name)
  3. the profile's api_key_command (a command whose stdout is the key)
  4. the profile's api_key (in the file — supported, discouraged)
  5. the provider's conventional variable, e.g. $ANTHROPIC_API_KEY

askcii config list reports which source each profile is using, so you can confirm no key is sitting in the file:

* work   anthropic/claude-sonnet-5  key: env:ANTHROPIC_API_KEY
  local  ollama/llama3.2            key: not required

Exit codes

Code Meaning
0 Success
1 General error
2 Usage error
3 Configuration error
4 Provider or network error
130 Interrupted
141 stdout closed early (e.g. piped to head)
askcii 'question' || case $? in
  2) echo 'I typed it wrong' ;;
  3) echo 'not configured' ;;
  4) echo 'provider is down, retrying later' ;;
esac

Recipes

# Commit messages
git diff --staged | askcii -p 'write a conventional commit message' | git commit -F -

# Explain a failure, with the exit code preserved
some-command 2>&1 | askcii 'why did this fail?'

# Pull one field out
askcii --json 'name three shells' | jq -r .content

# Local model for anything sensitive
askcii -P local -p 'summarize' < confidential.txt

# Batch, without hammering one session
find . -name '*.rb' | while read -r f; do
  askcii -p "one-line summary of $f" < "$f"
done

Shell aliases:

alias explain='askcii -p "explain this command:"'
alias review='git diff | askcii "review this:"'

Files

Path Contents
$XDG_CONFIG_HOME/askcii/config.yml Profiles (mode 0600)
$XDG_DATA_HOME/askcii/askcii.db History, SQLite (mode 0600)

Override with $ASKCII_CONFIG and $ASKCII_DATABASE.

Shell completion and the manual

Completions for bash and zsh are in completions/; see the README there. A man page ships as man/askcii.1:

man askcii

Upgrading from 0.x

Version 1.0 reorganizes the CLI. Your data is migrated automatically the first time you run it — configurations move from SQLite into the YAML file, named after their old names.

Before Now
askcii -c askcii config add (or config edit)
askcii -m 2 askcii -P NAME — profiles have names; -m now means the model
askcii --list-sessions askcii sessions list
askcii --history askcii sessions show
askcii --clear-history askcii sessions clear

The old flags still work for now and print a deprecation notice. -p, -r, and -v are unchanged.

Also fixed in 1.0: -p never worked (it crashed on every invocation), and user prompts were never saved, so --session replayed only the assistant's half of the conversation. Both are corrected — existing history is left as-is, so old sessions will look one-sided.

Development

bin/setup
bundle exec rake test      # 72 tests
bundle exec rake rubocop
bundle exec rake           # both
bin/askcii 'test prompt'

License

MIT