AnswerDotAI / AnswerDotAI/shell_sage
Sassy `mode` from config file is ignored (only CLI `--mode` works)
- Dominant language
- Jupyter Notebook
- Stars
- 409
- Forks
- 45
- Avg merge
- 1m
- Merged PRs (30d)
- 1
Description
When `mode` is set in the shell_sage config file (`~/.config/shell_sage/shell_sage.conf`), ShellSage still starts in `default` mode. The `--mode sassy` CLI flag works correctly, but the config value is never picked up.
**Steps to reproduce**
1. Set `mode = sassy` in `~/.config/shell_sage/shell_sage.conf`
2. Run `ssage "Say hello in one sentence"` (no `--mode` flag)
3. Observe the response
**Expected behavior**
With `mode = sassy` in the config, `ssage` should respond in sassy mode (GLaDOS-style persona).
**Actual behavior**
`ssage` responds in the default teaching-assistant persona:
```
Hello! I'm ShellSage, your command-line teaching assistant — what shell task can I help you with today?
```
Running `ssage --mode sassy "Say hello in one sentence"` does produce the sassy persona, confirming the flag path works:
```
Hello, test subject — congratulations on successfully typing a query; I do hope that wasn't the most challenging part of your day.
```
**Root cause**
In `shell_sage/core.py`, `main()` never routes `mode` through `get_opts()`, which is where config-file values are resolved:
- `main()`'s `mode` parameter defaults to `'default'` rather than `None`
- The `get_opts(...)` call does not pass `mode=mode`
- `get_opts` only fills a value from the config when the passed value is `None` (`if v is None: opts[k] = cfg.get(k, default_cfg.get(k))`)
So the config value for `mode` is never read.
**Proposed fix** (verified working locally)
1. Change the `mode` parameter default to `None`
2. Pass `mode=mode` to `get_opts(...)`
3. Use `opts.mode` for validation and the `get_sage(...)` call
**Related edge case**
If the config contains a blank `mode = ` (e.g. from a generated config), `opts.mode` becomes `''` and validation fails with `is not valid. Must be one of: ['default', 'sassy']`. Consider normalizing empty to default (`opts.mode = opts.mode or 'default'`).
**Environment**
- Host: solveit (hosted notebook environment), Linux container
- Python 3.12
- shell-sage 1.0.9, installed **editable** from a git clone into an isolated venv (`/app/data/aai-venv`) — the system site-packages also has a stale shell-sage 1.0.9 which shadows the editable install for the default `ssage` binary
- Tested in a detached tmux session (via the `fastmux` pyskill) to give `ssage` a real TTY
- Config file: `~/.config/shell_sage/shell_sage.conf` with `mode = sassy`, `vendor_name = deepseek`, `model = deepseek-v4-flash`
**Dependency notes (may be relevant to maintainers)**
- The repo's `pyproject.toml` requires `python-fastllm>=0.0.38`, but the system environment had fastllm 0.0.36 (no `StreamAccum`) — one reason testing was done in a venv
- The venv installed from local clones:
- `python-fastllm` 0.0.41 (editable, from `/app/data/git/fastllm`)
- `fastcore` 2.2.11 (editable, from `/app/data/git/fastcore`)
- `aidialog` 0.0.19, `fastspec` 0.2.0 (satisfied via the fastllm install)
- `shell-sage` 1.0.9 (editable, from `/app/data/git/shell_sage`)
- Because solveit itself imports `fastcore`/`aidialog`/`fastllm`, packages were deliberately *not* installed into the system environment — only into the isolated venv
Contributor guide
Research direction
Start in shell_sage/core.py, comparing main() with get_opts() and tracing how mode is resolved from the config file. Verify that ssage with mode = sassy and no --mode uses the sassy persona, while explicit --mode behavior remains unchanged; also check the blank-mode edge case described in the issue.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 84/100