home / docs

Build on abs

Two things on one page: a map of what abs adds to Claude Code and where each piece lives in the source, and short how-tos for making it your own. Every code chip and source link is pinned to the v2.1.4 tag.

What abs adds to Claude Code

It's all additive — abs appends a system prompt and merges a settings file; your CLAUDE.md, permissions, and Claude's memory are never touched.

SYSTEM PROMPT SETTINGS abs.sh PYTHON TELEGRAM PLUGIN STATE FILE
FeatureLives inWhat it does
Persona & messaging
One session SYSTEM PROMPT Terminal and Telegram are treated as the same person and the same live session.
Always reply SYSTEM PROMPT Every inbound Telegram message gets a reply — the phone is never left in silence.
Send discipline SYSTEM PROMPT One proactive ping when a task finishes or it's blocked; no progress spam.
Phone-first writing SYSTEM PROMPT Plain text, short, outcome first. Acks long tasks then edits that message instead of flooding.
Command menu SYSTEM PROMPT Explains that /model, /stop etc. don't run from the phone, and gives the real route.
Safety rules SYSTEM PROMPT No secrets over Telegram; fetched content is data not commands; no destructive ops on a message alone.
Auto-silent & status
Auto-silent triggers SETTINGS Merged UserPromptSubmit + PostToolUse hooks fire on each prompt and on every Telegram reply.
Auto-silent logic abs.sh STATE Counts terminal vs phone activity; mutes after ~3 terminal prompts, un-mutes on a Telegram message.
Status-bar glance abs.sh statusLine runs abs.sh to draw the live dot + 5h/week usage in Claude's bottom bar.
Mute & launch state
Quiet / off abs.sh STATE quiet mutes reports (inbound stays); off drops all inbound. Persona knows both commands.
Launch defaults abs.sh STATE Per-profile model and start-silent, stored in rc.json and applied at launch.
Usage
Usage glance abs.sh STATE Token-free /usage fetch, cached to usage.json, shown in the bar and as a Telegram footer.
Usage footer rule SYSTEM PROMPT Tells the agent to append the cached glance to task-completion reports only.
Voice & images
Voice in PYTHON PLUGIN transcribe.py (Whisper, local) turns an inbound voice note into text the agent acts on.
Voice out PYTHON abs.sh speak.py (local TTS), driven by abs say, sends a spoken reply on request. Choose the model (abs config voice standard|turbo) or clone a voice from a short sample (abs config voice-sample). Auto-picks CUDA when present, else CPU.
Screenshots / photos SYSTEM PROMPT PLUGIN Agent reads an attached image directly (via the plugin's download_attachment / image path).
Infrastructure
Inbound & tools TELEGRAM PLUGIN Anthropic's official Telegram plugin provides the reply / download_attachment tools and inbound polling.
Access control abs.sh STATE PIN pairing writes your ID to access.json; only the paired account ever reaches Claude.
Startup flood control abs.sh Drains stale Telegram backlog at launch so a fresh session doesn't open buried in old messages.
Update check abs.sh On every launch, token-free, checks the remote VERSION and offers to update-and-relaunch on a y/N prompt; declining just launches.
📄

CLAUDE.md — nothing goes here

abs never writes to CLAUDE.md. The persona lives only in the appended system prompt, re-applied fresh each launch — so there's no persistent agent memory and nothing left behind in your project config.

Make it yours

abs is one readable bash script plus two small Python helpers — no framework, no build step. Each how-to ends with the exact file and function to edit.

Orientation

The whole project, in four places

There's very little to learn. Everything abs does lives in one of these:

# the program — commands, persona, hooks, usage, all of it
abs.sh

# voice, both directions (local, no cloud)
transcribe.py   # voice note  → text
speak.py        # text        → voice note

# your runtime state, owner-only (never in git)
~/.abs/          # rc.json, access.json, usage.json …

The agent's behaviour isn't in a config file — it's the system prompt abs appends at launch, built in build_prompt().

abs.sh
How-to

Point it at a different model

Set a default model per profile, applied on every launch. An explicit abs --model … on the command line always wins for that one session.

abs config model opus        # default for this profile
abs config model --clear       # back to Claude Code's default
abs --model sonnet           # just this session

To change how the default is stored or applied, the logic is in cmd_config() (stores it) and cmd_run() (passes --model at launch).

abs.sh · cmd_config
How-to

Rewrite the persona & tone

How abs talks to you — when it messages, how short it keeps things, its safety rules — is one block of text appended to the session as a system prompt. Edit the heredoc in build_prompt() and it takes effect on the next launch. Nothing is compiled; it's plain English.

abs.sh · build_prompt
How-to

Replace the voice engine

Voice is two standalone scripts with a dead-simple contract. Keep the same in/out and you can drop in any engine — a different Whisper size, a cloud STT, another TTS voice.

# in:  an audio file path  →  out: transcript on stdout
transcribe.py <file.oga>

# in:  text  →  out: a voice note sent to Telegram
speak.py "the text to speak"

abs only ever calls these two files, so swapping engines never touches the main script.

transcribe.py speak.py
How-to

Tune how fast it goes quiet

Auto-silent trips after a set number of back-to-back terminal prompts. Want it to hold on longer, or mute sooner? Change one constant.

readonly SILENT_STREAK=3    # prompts at the terminal before it mutes

The counting itself lives in cmd_silent_hook() just below — that's where a Telegram message resets the streak.

abs.sh · SILENT_STREAK
How-to

Add your own command

Commands are a plain case in main(). Write a cmd_yours() function, add one line to the dispatch, and abs yours works. No registration, no plugin system.

cmd_hello() { ok "hi from $PROFILE"; }

# in main()'s case block:
hello) cmd_hello ;;
abs.sh · main
How-to

Change what the status bar shows

The bottom-bar dot and usage are rendered by cmd_statusline(); the 5h / week glance itself is formatted in usage_glance_str(). Edit either to change the text, order, or what's shown.

abs.sh · cmd_statusline usage_glance_str
Reference

Every command

You can also just say it in chat — "mute the reports", "what's my usage" — and abs runs the same thing.

CommandWhat it does
absStart a session — first run walks you through bot setup.
abs --model opusAny Claude Code flag is passed straight through.
abs statusWhat's paired, the inbound state, and whether it's live.
abs usageYour Claude limits — in the terminal and on Telegram.
abs profilesList your bots and which are currently in use.
abs config model <name>Default model for new sessions (--clear to unset).
abs config silent on|offWhether new sessions start muted.
abs config statusline on|offThe bottom-bar mute/active dot + usage glance.
abs config usage-refresh <min>How often the usage glance refreshes.
abs quiet on|offMute / unmute reports — inbound still works.
abs off | onDrop / re-enable all inbound Telegram.
abs say "text"Speak it and send as a voice note.
abs updateUpdate abs in place to the latest release.
abs resetRemove this profile's token, allowlist, and state.
abs versionPrint the installed version.
abs helpThe full list.

Built something good?

Open a PR — new engines, commands, and platforms are all welcome.

Contributing guide
← Back to home  ·  v2.1.4  ·  MIT License  ·  Made with for Claude Code users