Collapse ??? web-search and ?: state into one ??? memory verb - #3
Merged
Conversation
? had grown 12 flags that mixed two ideas (asking and managing state). The state ops now live behind a single meta verb so the asking commands stay ask-only. New surface - `?:` — long-term facts + cross-session recall - `?: add <fact>` / `list` / `drop <n>` / `recall <q>` / `status` - `,` is now session-aware (cmd="comma"): follow-ups refine the prior proposal instead of asking from scratch. Same TTL/archive hookup as `?` / `???`, so expired `,` sessions are searchable via `?: recall`. Removed from `?` / `???` - --remember, --memories, --forget, --recall, --mem, --no-mem Deprecation - Moved flags print a one-line redirect pointing at the `?:` equivalent so muscle memory fails loudly, not silently. Surfaces that stay - `? --new / --reset / --history / --compact / --auto-recall / --help` - `, --new / --reset / --history / --help` - `??` and its `--start-embed` extension unchanged 168 tests (was 144), ruff clean.
…ory verb
Before this change the CLI had five commands: `,`, `?`, `??`, `???`,
`?:`. `???` was just `?` with a "web-first" system prompt, and `?:`
held the durable layer (facts + recall). Both were artifacts of growth
rather than orthogonal concepts. This commit collapses them.
New shape (four commands, each one job)
- `,` propose shell commands (sticky session, unchanged)
- `?` ask (sticky session, model picks tools — incl. web)
- `??` llama-server control (unchanged)
- `???` memory layer: bare query searches the archive; subcommands
manage facts (add/list/drop/status/help). Explicit `recall <word>`
when the query happens to start with a subcommand verb.
`?` gains `--web` / `-w` for the rare case you want to force a
web-first answer this turn — same agent loop, same session bucket
(cmd="ask"), just a stronger system-prompt nudge.
`???` gains `--ask` / `--comma` filter flags so you can scope recall
to one type of session ("only my asks", "only my command proposals").
Deletions (no deprecation hints — clean cut)
- src/shellllm/search.py — `???` web-search command
- src/shellllm/state.py — `?:` state command
- tests/test_state.py
- Entry points: shellllm-search, shellllm-state
- Zsh: SHELLLM_SEARCH env, _shellllm_search_fn, alias `?:`
Adds
- src/shellllm/recall.py — the new `???` command
- tests/test_recall.py — dispatch + filter flag coverage
- tests/test_ask_web_flag.py — verifies --web swaps system prompt
- Entry point: shellllm-recall
- Zsh: SHELLLM_RECALL env, _shellllm_recall_fn
178 passing tests (was 168), ruff clean.
Mode ops are now flags (--add / --list / --drop / --status) instead of subcommand verbs. Bare-word input is unambiguously a recall query; no more "is this a subcommand or a search term?" overload. Surface - ??? <q> bare query → recall - ??? --add <fact> was: ??? add - ??? --list was: ??? list - ??? --drop <n> was: ??? drop - ??? --status was: ??? status - ??? --ask / --comma <q> filter recall (unchanged) - ??? --help was: ??? help Validation - Mode flags are mutually exclusive (two → error) - Filter flags are mutually exclusive (two → error) - Filter + mode flag → error (facts are global, not per-command) - Per-mode extra-arg checks (--list takes no args, --drop takes one, etc.) 181 passing tests (was 178), ruff clean.
…n hint
Two new mode flags on ???:
- --archives [n] list n most-recent archived sessions (default 20),
one row per archive with id · cmd · ts · pwd · snippet.
Honors --ask / --comma to narrow by command.
- --show <id> print the full transcript of one archive.
Together they fill the "how do I see what's in here?" gap that --status
left open (it only reported counts).
Filter compatibility
- --archives accepts --ask / --comma (per-command browse makes sense)
- --show <id> targets exactly one row, so filters error there
- Facts ops stay global-only (--add / --list / --drop / --status)
Visual bug fix in `,`
The "↻ refining — turn N" / "↻ idle session expired" hints in comma
were written via `rich.Console.print`, which strips embedded ESC bytes
as a safety measure — leaving `[2m[36m...[0m` visible as literal text.
Replaced with a sys.stderr.write helper matching ask._note. Added a
regression test that asserts ESC bytes survive in stderr output.
197 passing tests (was 181), ruff clean.
Restructured for the GitHub-frontpage skim test: - Single tagline above the fold - Hero block showing the three core commands working back-to-back - Quick-reference table for the four glyphs - Tiers as a side-by-side comparison, not prose - 'Why this exists' moved up to anchor the contrarian take (offline, local 27B, no per-question cost) - Configuration as one long table instead of paragraphs Architecture / hard wall / dev sections still present but moved below the fold so they don't drown the install path.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The CLI had grown to five commands —
,???????:— but two of them weren't orthogonal:???was just?with a "web-first" system prompt?:(the colon-glyph state verb) split memory ops from the restThis collapses them into one
???verb whose meaning matches its shape: three question marks reads as "I'm trying to remember…".New shape
Four commands, each one job:
No bare-word verbs on
???— everything other than a recall query is a flag. Bare words (??? list) are unambiguously recall queries.Why this is the win
?is the question. Web search is a tool the agent has — forcing it is a flag (--web/-w), not a sibling command.???gets a coherent role. "Three question marks" reads as "I'm trying to remember…". Bare??? what was that grep flagis the most natural recall syntax; flags kick in only for fact management.?:, no?., no?!. Four commands total.shellllm-searchis gone; the system prompt that made???web-first becomes a one-flag variant of?.???other than recall is a flag.Filter flags on
???Recall hits across all session types by default. Filter when needed:
Combining a filter with a mode flag errors (facts are global, not per-command).
Validation
--listtakes no args;--droptakes exactly one; etc.)Cuts vs. adds
Deleted (no deprecation redirects — clean cut):
src/shellllm/search.pysrc/shellllm/state.pytests/test_state.pyshellllm-search,shellllm-stateSHELLLM_SEARCH,_shellllm_search_fn, alias?:Added:
src/shellllm/recall.pytests/test_recall.pytests/test_ask_web_flag.pyshellllm-recallSHELLLM_RECALL,_shellllm_recall_fnTest plan
ruff checkcleanruff format --checkclean??? --add,??? --list,??? <bare query>,??? --ask, mutually-exclusive flag rejection,?:confirmed removed? --webagainst a running llama-server to confirm the web-first system prompt actually fires