Core

Imports


source

CodeBlock.__rich_console__

 CodeBlock.__rich_console__ (console, options)

source

Chat

 Chat (*arg, **kw)

Lazy load lisette to make ssage more responsive

Jupyter does work with rich.live.Live, this fixes it.

@contextmanager
def Live(start, **kw):
    print(start)
    def update(s, refresh=False): clear_output(True);print(s)
    yield NS(update=update)
def print_md(md_stream):
    "Print streamed markdown"
    with Live(Spinner("dots", text="Connecting..."), auto_refresh=False) as live:
        for part in md_stream: live.update(Markdown(part), refresh=True)

Model Setup

System Environment

# aliases = _aliases('bash')
# print(aliases)
# print(_sys_info())

Tmux


source

get_pane

 get_pane (n, pid=None)

Get output from a tmux pane

# p = get_pane(20)
# print(p[:512])

source

get_panes

 get_panes (n)
# ps = get_panes(20)
# print(ps[:512])
co(['tmux', 'display-message', '-p', '#{history-limit}'], text=True).strip()
'2000'

source

tmux_history_lim

 tmux_history_lim ()
tmux_history_lim()
2000

source

get_history

 get_history (n, pid='current')

Options and ShellSage


source

get_opts

 get_opts (**opts)
# opts = get_opts(model=None, log=None, api_base=None, api_key=''); opts

source

with_permission

 with_permission (action_desc)
print(tools[1]('.'))
Directory contents of /Users/jhoward/aai-ws/shell_sage/nbs:
/Users/jhoward/aai-ws/shell_sage/nbs/00_core.ipynb
/Users/jhoward/aai-ws/shell_sage/nbs/_quarto.yml
/Users/jhoward/aai-ws/shell_sage/nbs/sidebar.yml
/Users/jhoward/aai-ws/shell_sage/nbs/styles.css
/Users/jhoward/aai-ws/shell_sage/nbs/CNAME
/Users/jhoward/aai-ws/shell_sage/nbs/01_config.ipynb
/Users/jhoward/aai-ws/shell_sage/nbs/nbdev.yml
/Users/jhoward/aai-ws/shell_sage/nbs/index.ipynb

source

get_sage

 get_sage (model, mode='default', search=False)
# m = 'ollama_chat/qwen3:8b'
# ssage = get_sage(m)
# ssage('Howdy!')
m = 'claude-sonnet-4-5'
ssage = get_sage(m, search='l')
ssage('Hi, how are ya?', think='l')

Hey there! Doing well, ready to help with any shell commands or system questions you’ve got. What can I help you with today?

  • id: chatcmpl-30420d10-6b60-492d-9c90-0933442e7e6c
  • model: claude-sonnet-4-5-20250929
  • finish_reason: stop
  • usage: Usage(completion_tokens=91, prompt_tokens=3387, total_tokens=3478, completion_tokens_details=CompletionTokensDetailsWrapper(accepted_prediction_tokens=None, audio_tokens=None, reasoning_tokens=46, rejected_prediction_tokens=None, text_tokens=None, image_tokens=None), prompt_tokens_details=PromptTokensDetailsWrapper(audio_tokens=None, cached_tokens=0, text_tokens=None, image_tokens=None, cache_creation_tokens=0, cache_creation_token_details=CacheCreationTokenDetails(ephemeral_5m_input_tokens=0, ephemeral_1h_input_tokens=0)), cache_creation_input_tokens=0, cache_read_input_tokens=0)

source

get_res

 get_res (sage, q, opts)
opts=NS(api_base='', api_key='', think='l')
list(get_res(ssage, 'Use tools to check if we have a  .git in the current directory. Respond with yes/no', opts))
['', '', '', '', '', '', '', '', '', '', '', '', '', '', 'No', 'No']
print_md(get_res(ssage, 'Hi!', opts))
Hey! What can I help you with?                                                                                     
print_md(get_res(ssage, 'Please use your view command to see what files are in the current directory. Only respond with a single paragraph', opts))
The current directory contains several files related to what appears to be an nbdev project: three Jupyter         
notebooks (00_core.ipynb, 01_config.ipynb, and index.ipynb), along with configuration files for Quarto             
(_quarto.yml, sidebar.yml, styles.css), a CNAME file for custom domain hosting, and an nbdev.yml configuration     
file.                                                                                                              
print_md(get_res(ssage, 'Please search the web for interesting facts about Linux. Only respond with a single paragraph.', opts));
Linux, created in 1991 as an open-source Unix-like operating system, has revolutionized the world and become the   
dominant OS in cloud computing, IoT, and mobile devices, with all 500 of the world's fastest supercomputers running
Linux. The operating system almost wasn't called "Linux" — Linus Torvalds originally wanted to name it "FreaX" but 
was persuaded by the server owner hosting his early code to use "Linux" instead, and the International Space       
Station has been running Linux since 2013. The penguin mascot Tux has an amusing origin story: Linus claims he was 
once bitten by an angry penguin, and Linux has even made its mark in Hollywood, with the visual effects for Avatar 
and Titanic developed on the Linux platform.                                                                       

Logging


source

mk_db

 mk_db ()

source

Log

 Log ()

Initialize self. See help(type(self)) for accurate signature.

# db = mk_db()
# log = db.logs.insert(Log(timestamp=datetime.now().isoformat(), query='Hi, who are you?', model='llama3.2',
#                          response='I am ShellSage, a command-line teaching assistant!', mode='default'))
# log

Main


source

main

 main (query:str<ThequerytosendtotheLLM>, v:<Printversion>='%(prog)s
       1.0.2', pid:str='current', skip_system:bool=False,
       history_lines:int=None, mode:str='default', model:str=None,
       search:str=None, api_base:str=None, api_key:str=None,
       think:str=None, trust:str=None, code_theme:str=None,
       code_lexer:str=None)
Type Default Details
query str
v %(prog)s 1.0.2
pid str current current, all or tmux pane_id (e.g. %0) for context
skip_system bool False Whether to skip system information in the AI’s context
history_lines int None Number of history lines. Defaults to tmux scrollback history length
mode str default Available ShellSage modes: [‘default’, ‘sassy’]
model str None The LLM model that will be invoked on the LLM provider
search str None Wheather to allow the LLM to search the internet
api_base str None
api_key str None
think str None Reasoning effort level: ‘l’, ‘m’, ‘h’ (for supported models)
trust str None Comma-delimited list of tools to always allow (e.g. “view,rg”)
code_theme str None The code theme to use when rendering ShellSage’s responses
code_lexer str None The lexer to use for inline code markdown blocks
main(['Teach me about rsync. Reply with a single paragraph.'], history_lines=0)
rsync is a fast, versatile file-copying tool that efficiently transfers files by only sending differences between  
source and destination (delta transfer). Common usage: rsync -avz source/ dest/ where -a is archive mode (preserves
permissions, timestamps, symlinks), -v is verbose, and -z compresses during transfer. For remote sync: rsync -avz  
local/ user@host:/remote/path/. Key gotcha: trailing slash matters—source/ copies contents, source copies the      
directory itself. Use --dry-run to preview changes before committing, and --delete to remove files from dest that  
don't exist in source (destructive). See man rsync for the full 100+ options.                                      
r = f'''
Hello, user! Here are some code blocks:

```python
for i in range(10): print(i)
```

```
This doesn't even have a language definition!
```

```bash
ls **/*
```
'''
db = mk_db()
db.logs.insert(Log(timestamp=datetime.now().isoformat(), query='', response=r, model='', mode=''))
Log(id=1, timestamp='2025-12-03T04:46:49.790878', query='', response="\nHello, user! Here are some code blocks:\n\n```python\nfor i in range(10): print(i)\n```\n\n```\nThis doesn't even have a language definition!\n```\n\n```bash\nls **/*\n```\n", model='', mode='')

source

extract_cf

 extract_cf (idx)
extract_cf(0)
'for i in range(10): print(i)'

source

extract

 extract (idx:int, copy:bool=False)
Type Default Details
idx int Index of code block to extract
copy bool False Copy to clipboard vs send to tmux