Pular para o conteúdo principal

Input routing

Parolsh never guesses whether a line is English or a shell command. The first character decides, always:

InputRoute
textThe active ACP agent
?textThe active ACP agent
/commandThe active ACP agent, unchanged
!commandThe configured shell, default bash -ic
!+commandThe same, and its output goes with your next message
!bashAn interactive Bash session
#commandParolsh itself
! aloneLock: plain text goes to the shell, see Shell mode
? aloneUnlock: plain text goes to the agent again

find files modified today is always a question for the agent. To run the Unix find, type !find . -mtime -1.

Shell mode​

When you run many commands in a row, ! alone locks plain text to the shell, and ? alone unlocks it. The prompt's last symbol shows where plain text goes:

[claude] ~/projects/wallet ✦ !
[claude] ~/projects/wallet ❯ git status ← bash
[claude] ~/projects/wallet ❯ ?why is main behind? ← the agent
[claude] ~/projects/wallet ❯ ?
[claude] ~/projects/wallet ✦ what changed today? ← the agent

A real session, locked to bash, sharing a diff with the agent, then unlocked:

A Parolsh session: ! locks plain text to bash and the prompt changes from ✦ to ❯; git status runs in bash; !+git diff shows the diff and keeps it for the agent; ?what did I change asks Claude, which explains the change; ? unlocks back to ✦

InputAgent mode ✦ (default)Shell mode ❯
textthe agentthe shell, like !text
?textthe agentthe agent
/commandthe agentthe shell (/usr/bin/ls runs); ?/command reaches the agent
!command, !+command, !bashthe shellthe same
#commandParolshParolsh

Unlike !bash, shell mode stays in Parolsh: the agent is a ? away, !+ shares output with it, and # commands work. Each command runs in its own shell, but a cd and the variables you export carry over to the next (see !command). The mode lasts until you change it or leave Parolsh.

To start in shell mode, set input = "shell" in config.toml (see Configuration), or run parolsh --input=shell; --input wins over the file. A project's .parolsh/config.toml can set it too: #cd into a project whose input differs switches to it. Without an agent configured, Parolsh always starts in shell mode.

While you type​

On an ANSI terminal the line shows where it will go before you press Enter:

LineColor
!command, !bashyellow
!+commandgreen
#commandmagenta
/commandblue
text for the agentthe terminal's color

In shell mode, plain text is a shell command, so it is yellow too. The marker (!, !+, #, /) is bold. While the line is only a marker, a dim hint says what it does, for example !+ run a shell command and send its output with your next message. The hint is a tip: the right arrow does not insert it into the line.

Tab completion​

On !command and !+command lines, and plain lines in shell mode, Tab completes the word at the cursor, as bash does: a single match goes into the line, several fill in what they have in common, and the next Tab shows them in a menu (Tab and Shift+Tab move through it, Enter picks one).

  • The command name completes from the programs on your PATH and, when the shell is bash, from the aliases, functions and builtins your ~/.bashrc sets up. That list is read once, in the background, when Parolsh starts: an alias added later shows up the next time.
  • A command's arguments complete as bash would, when the shell is bash and bash-completion is installed: git branches and subcommands, ssh hosts, systemctl units, --flags. It uses the completions bash-completion ships, those in ~/.local/share/bash-completion/completions/ and ~/.bash_completion, but not the ones your ~/.bashrc defines (complete -C ..., source <(kubectl completion bash)): put those in ~/.bash_completion to get them. !bash has your full bash completion.
  • Other words, and arguments bash-completion has nothing for (or takes more than half a second to find), complete as file and directory names, from the directory your commands run in. ~/ and absolute paths work, hidden files show up when the name starts with ., and special characters are escaped (My\ Files).

On # lines, Tab completes the command's name (#a gives #agent and #audit), and after #cd a directory, from the directory your commands run in. #cd takes the path as typed, so names with spaces are not escaped there (#cd My Projects/). After #resume, #audit and #forget, it lists this project's sessions to pick one, see Resuming a session. Other # commands have no arguments to complete.

In text for the agent (?text in shell mode), Tab completes @path with a file or directory name from where your commands run, escaped like on a shell line (@My\ Notes.md); see Mentioning files. A / that starts the text completes one of the agent's own commands, see /command. Other words of the text have no completion.

!command​

The command runs as bash -ic "<command>", in the directory the last command ended in.

  • Your ~/.bashrc is loaded, so aliases, functions and shell options work as in your normal terminal. The shell is interactive (-i) because a plain bash -c ignores aliases, and the stock Debian/Ubuntu ~/.bashrc stops right away when the shell is not interactive.

  • A cd carries over. When a command ends, its shell tells Parolsh the directory it ended in, and the next command runs there: cd src, cd -, pushd, a cd before exit 1.

  • So do the variables you export. export FOO=1, unset FOO, source .envrc, nvm use 20, source venv/bin/activate: what a command changed in its exported variables is applied again before the next one, after your startup files, so it wins over them as in a terminal (the virtualenv stays first in PATH). For each variable the last value replaces the one before.

    [claude] ~/projects/wallet ❯ source venv/bin/activate
    [claude] ~/projects/wallet ❯ which python
    /home/joao/projects/wallet/venv/bin/python

    Only exported variables: a plain FOO=1, an alias or a function defined in a line is gone when it ends (so a virtualenv's deactivate is not there; set -a; source .env; set +a exports a file of plain KEY=value lines). !bash starts with these changes, and is a session that keeps all of its state. They are kept in memory until you leave Parolsh, and are not given to the agent: it keeps the environment it started with.

  • The agent stays where it is. A cd moves your commands, not the conversation: the agent keeps working in the directory it started in, and the prompt shows both while they differ:

    [claude] ~/projects/wallet ✦ !cd /var/log
    [claude ~/projects/wallet] /var/log ✦ #cd . ← brings the agent here
    [claude] /var/log ✦

    #cd . starts a new conversation in the directory of your commands. The outputs you share with !+ say where they ran.

  • The directory comes back through the shell's EXIT trap, so the shell must understand trap (bash, zsh, dash do). A command that ends with exec, or is killed, leaves the directory as it was.

  • Commands stay out of your bash history. Parolsh sets HISTFILE=/dev/null for them and keeps its own history.

  • A non-zero exit code is printed after the output, for example exit 1.

  • Ctrl+C stops the running command, not Parolsh.

  • Parolsh has no job control for your commands (for the agent's turns, see Turns in the background). With the default bash -ic, Ctrl+Z is handled by that bash, as if you had typed the line in bash: the running program is paused (Stopped), the rest of the line continues, and the paused program ends when the command finishes. With a non-interactive shell such as ["bash", "-c"], Parolsh resumes the command right away. Use !bash when you need job control.

Loading ~/.bashrc costs a little time on every command (about 0.17 s on a typical Ubuntu setup). Anything ~/.bashrc or /etc/bash.bashrc prints also shows up in the output.

The shell is configurable, see Configuration:

shell = ["zsh", "-ic"]

!+command​

Runs the command like !command, shows its output, and keeps it for the agent: it is sent with your next message, then forgotten.

[claude] ~/projects/wallet ✦ !+docker ps
CONTAINER ID IMAGE STATUS
...
(output of `docker ps` goes with your next message)
[claude] ~/projects/wallet ✦ which of these containers looks unhealthy?

The agent answers from that output instead of running the command again.

  • Only commands you mark with !+ are shared: a plain !command never reaches the agent.
  • Several !+ commands before one message are all sent, in order, each with its command, directory and exit code.
  • At most the last 16 KB of each output is sent.
  • The command's output goes through Parolsh, so programs see a pipe instead of a terminal: they print plain text, without colors or pagers. Full-screen programs (vim, top) belong to a plain !. Its input is still the terminal, so a sudo password prompt works.
  • !+ alone shows how to use it.

!bash​

Opens a real interactive Bash in the directory of your commands, with your full ~/.bashrc and completions. exit returns to Parolsh, in the directory it was in before: changes made inside the session stay there.

Text​

Anything that does not start with !, # or / is a question for the agent, in agent mode (in shell mode, start it with ?). The answer is printed as it arrives, with a status line showing what the agent is doing (see During a turn). Ctrl+C cancels the turn.

Mentioning files​

@path names a file or directory for the agent:

[claude] ~/projects/wallet ✦ why does @src/api/client.rs retry twice?

The text goes as typed, and each @path that exists goes with it as a link (an ACP resource_link with the absolute file:// path), which the agent reads itself. Paths start where your commands run, the directory the prompt shows; ~/ and absolute paths work.

After a cd took your commands away from the agent's directory, that is still where @ starts and what Tab completes:

[claude ~/projects/wallet] ~/projects/wallet/infra ✦ why does @deploy.yaml fail?

The link is infra/deploy.yaml. The agent would read the word @deploy.yaml from its own directory, so it gets it in full, @/home/you/projects/wallet/infra/deploy.yaml, while the history keeps what you typed.

@words that name nothing (@team, an email address) are only text, and punctuation right after a path (@notes.txt.) is not part of it. #audit shows how many files a message linked.

Not on ! lines: there, @ is the shell's.

/command​

Lines starting with / belong to the agent. Parolsh reserves no / commands and forwards the line as typed, so the agent's own slash commands work.

Tab completes them, from the list the agent itself sends when a conversation opens, and again when it changes:

[claude] ~/projects/wallet ✦ /co<Tab>
/compact Compact the conversation ([instructions])
/cost Show what the session cost
  • One match goes into the line; several show in a menu, each with what the agent says of it and, in parentheses, what it takes after its name.
  • They are the running agent's, and they differ: /compact for Claude, Codex, OpenCode and Goose, /compress for Qwen Code. Those five and Kilo Code send their list, with their skills in it; an agent that sends none has nothing to complete. A command the agent takes without listing it (Kilo's /compact) still works when typed.
  • Only the command's name, where it starts the text for the agent (after ? in shell mode). What follows it is not completed, and / elsewhere in a sentence is a path like any other word.

#command​

CommandWhat it does
#helpShow the input rules and commands
#newStart a new conversation with the agent, in the agent's directory
#new privateStart a new conversation that is not saved in the history, until the next #new, #cd or #agent
#cd <path>Change Parolsh's directory, for the agent and your commands, and start a new conversation there. ~ and relative paths work, from the directory of your commands, so #cd . brings the agent where a cd took them; no path means your home directory. Reloads the configuration of the project found there. An agent chosen with #agent stays when that project configures it; otherwise the project's default_agent is used, and the agent restarts if it changed.
#agentShow the agent in use
#agent listList configured agents; * marks the one in use
#agent <name>Switch to another configured agent, with a new conversation. default_agent does not change.
#optionsShow the running agent's options, * on the current values
#options <id> <value>Set one of the agent's options until you leave Parolsh
#configShow the configuration files in use, and whether they exist
#config samplePrint the full sample configuration
#promptShow the prompt style in use
#prompt <name>Switch the prompt: parolsh, starship or minimal, until you leave Parolsh
#projectShow the project root
#project initCreate .parolsh/ in the current directory
#auditWhat happened since Parolsh started, see #audit
#audit <n>What happened in session n, of any project, from the history
#sessionsThe sessions of this project saved in the history, newest first; * marks the current one
#sessions <text>The ones where the text was said, or that it titles, see Finding a session
#sessions all [text]The same over every project
#sessions agentThe conversations the running agent itself has for this directory, also the ones it had outside Parolsh. See A conversation the agent had elsewhere
#forget [n]Remove session n of this project from the history, after asking; the current one without n
#resume <n>Go back to session n with its agent, in its directory: the agent remembers that conversation, and what follows is saved in it. Claude, Codex and OpenCode can; an agent that cannot says so. A session of another project is resumed after asking
#resume <text>Go back to the one session of this project that has the text; #resume all <text> looks in every project
#resume agent <text>Go back to one of the agent's own conversations, by its title or the start of its id; it is recorded as a session
#share [n]Let the agent of this conversation read session n of another project with its history tools; without n, what is shared. See Sharing a session of another project
#redraw [n]Clear the terminal and show the last n exchanges of the conversation again (5 without n), see Showing the conversation again. Ctrl+L does the same
#copy [n]Copy the last answer to the clipboard as the agent wrote it; n: an earlier one (2 is the one before). Alt+C copies the last. See Copying an answer
#copy codeCopy the last code block of the last answer
#raw [n]Print the last answer, or an earlier one, without the layout of the screen
#jobsThe agent's turns sent to the background with Ctrl+Z, see Turns in the background
#fg [n]Wait for background turn n, or the last one. Ctrl+C cancels it, Ctrl+Z goes back to the prompt
#exitLeave Parolsh (Ctrl+D also works). While a turn or a task of the agent runs in the background, the first one says so and stays: leaving stops them

Copying an answer​

On screen an answer is laid out for reading: a mark, an indent, lines broken at the terminal's width. A selection with the mouse takes all of that with it. #copy, or Alt+C, puts the last answer on the clipboard as the agent wrote it, its markdown and nothing else:

[claude] ~/projects/wallet ✦ #copy
The last answer is on the clipboard (12 lines, with xclip).
[claude] ~/projects/wallet ✦ #copy code
The last code block of the last answer is on the clipboard (3 lines, with xclip).
  • #copy 2 is the answer before the last, and so on, for the last 20 of this run. An answer is all the agent wrote in a turn; a turn that ended in the background counts when it is reported.
  • #copy code takes the last fenced block of the last answer, without its fence: the command to run, the file to save.
  • #raw [n] prints the same text instead, to select it with the mouse.

Parolsh gives the text to the program of your desktop: wl-copy on Wayland, xclip or xsel on X11, pbcopy on macOS. Without one, as over SSH, it asks the terminal to take it (an OSC 52 request): kitty, WezTerm, Alacritty, foot, iTerm2, Windows Terminal and tmux do; GNOME Terminal and other VTE terminals do not, and say nothing. clipboard in the global configuration sets another command.

The answers are kept in memory, not read back from the history: after Parolsh restarts, #copy has the answers of the new run only.

#audit​

#audit lists what happened since Parolsh started, oldest first: what ran on your machine, what reached the agent, what the agent did, and what you answered.

[claude] ~/projects/wallet ✦ #audit
0:12 USER !kubectl get pods · exit 0
0:20 USER !+kubectl logs api · exit 0 · 12 KB kept
0:31 SHARED 1 output(s), 12 KB → claude
0:31 USER → claude: why is the api crashing?
0:44 AGENT execute: kubectl describe pod api · completed
0:52 AGENT asks: Writing to src/foo.rs
0:55 USER → Allow once
0:58 AGENT edit: Write src/foo.rs [src/foo.rs] · completed
1:03 PAROLSH turn ended · 32s
WhoWhat
USER!command, !+command and !bash with their exit code, your messages (their first line) with the agent they went to, # commands, and your answers to the agent's questions
SHARED!+ output sent with a message, and its size
AGENTTool calls, with their kind, the files the agent names and how they ended; permission requests and questions
PAROLSHHow each turn ended, a cancel the agent did not confirm, an agent that stopped

It keeps titles and commands only, the first line of each and at most 200 characters: outputs and answers stay in the scrollback. It is in memory, and gone when you leave Parolsh; for a full record, see Logging the agent's messages. It keeps the last 1000 entries and says how many older ones were dropped; audit_entries in the configuration changes that, and 0 turns it off. What the agent does without telling (a tool it does not report) is not there: see Security model.

The history of sessions​

Parolsh also saves each conversation in a history, so you can look back at it after you leave: history.db (SQLite) in $XDG_STATE_HOME/parolsh/ (~/.local/state/parolsh/), readable only by you, one file for every project.

[claude] ~/projects/wallet ✦ #sessions
* 14 2026-10-02 15:27 claude 23 entries 412k tok $1.84 Fix the crashing api
11 2026-09-30 10:02 claude 41 entries 1.2M tok $4.31 Add retries to the client
[claude] ~/projects/wallet ✦ #audit 11
0:00 USER → claude: the client gives up too early
0:09 AGENT read: Read src/client.rs [src/client.rs] · completed
0:15 AGENT answer: It retries once, with no backoff. …
...
  • A session is one conversation: it starts with Parolsh, #new, #cd or #agent, and is saved from its first entry. #sessions names it with the agent's title (Claude and Codex give one), or your first message.
  • #sessions also says what each session used, when the agent reports it (Claude, Codex, Kilo Code and OpenCode do, Qwen Code does not): the tokens of all its turns, and the cost for the agents that give one (see The context and what it costs). The total counts what was sent, received, reasoned, and read from and written to the agent's cache; most of it is cache reads, which cost far less. The four are kept apart with each turn, with the model that answered: see Usage in the database.
  • It keeps what #audit shows, with the full text instead of a short line, and also the agent's answers and reasoning, and the outputs shared with !+. #audit <n> shows answers as one line each; reasoning is not shown.
  • Your !command lines are saved for you, not for the agent. The line and its exit code, never its output, typed with ! or in shell mode: #redraw, a resumed session and #audit <n> show them (!cargo test · exit 101), and the tools the agent searches the history with leave them out. commands = "shared" gives them to the agent too (the banner then says so), and commands = "off" does not save them. A !+ command is always saved and returned to the agent: its output was sent to it.
  • Sessions belong to the project (its root, or the agent's directory without one): #sessions lists this project's, and #forget only removes one of them. Their numbers are the same everywhere, never given twice: see Finding a session for the other projects'.
  • A session idle for more than 90 days is removed when Parolsh starts; history_days changes that, and 0 saves nothing. #forget removes one now, and #new private starts a conversation that is not saved.

history_days and commands can only be set in the global configuration.

Finding a session​

#sessions takes the text to look for, and all for every project:

#sessionsThis project's sessions
#sessions <text>Those where the text was said, or that it titles
#sessions allThe sessions of every project
#sessions all <text>The same search over every project
[claude] ~/projects/wallet ✦ #sessions retry
11 2026-09-30 10:02 claude 41 entries 1.2M tok $4.31 Add retries to the client
agent: It [retries] once, with no backoff. …
[claude] ~/projects/wallet ✦ #sessions all falcon
27 2026-10-02 09:14 codex 18 entries billing Billing rewrite
you: the rewrite is called [falcon]
11 2026-09-30 10:02 claude 41 entries 1.2M tok $4.31 wallet Add retries to the client
command: cargo test [falcon]
  • Under each session, the line the text is in, and whose it is: yours, the agent's, or one of your !command lines, which are searched too. This search is yours, at the prompt: the agent's own search stays in this project and leaves your commands out. #share <n> gives it a session of another one.
  • It matches words, not meanings, and all of them: retry client finds the entries that have both.
  • Newest first, 20 at most; a line says how many more there are.
  • With all, each session's project, by the name of its directory. #resume says the whole path before going there.
  • #audit <n> shows a session of any project: it only looks.
  • Parolsh reads its history itself: no agent is asked, and it works without one.

Resuming a session​

#resume <n> goes back to session n: Parolsh moves to its directory and agent if needed, and asks the agent to reopen that conversation (ACP session/resume, or session/load when that is all the agent offers; the conversation it replays is not printed again). The agent then remembers everything that was said, and the session goes on in the history.

[claude] ~/projects/wallet ✦ #resume 11
Resumed session 11: the agent remembers that conversation.
[claude] ~/projects/wallet ✦ and the timeout, did we change it?

From the command line, parolsh --resume 11 starts in that session, and parolsh --continue in the last one of the project. Either way, Parolsh first shows the session's last exchanges, so you see where it was.

#resume <text> goes back to the one session of this project that has the text, as #sessions <text> finds it; when several have it, it lists them. #resume all <text> looks in every project.

A session of another project is said, and asked about, before anything moves: going there is what #cd does (that project's configuration, maybe another agent), and it ends the conversation you are in.

[claude] ~/projects/wallet ✦ #resume 27
Session 27: "Billing rewrite", ~/projects/billing, 2026-10-02 09:14.
Go there? [y/N] y
Now in ~/projects/billing (project).
Resumed session 27: the agent remembers that conversation.

Anything but y stays where you are. parolsh --resume 27 from another directory asks the same.

A number is easily mistyped, and the one next to it is a session too:

  • Tab after #resume, #audit or #forget lists this project's sessions with their date, agent and title, to pick one instead.
  • #forget says which session it is and asks before removing it: that one cannot be undone.
  • A session whose directory no longer exists, or whose agent is not configured any more, is not resumed, and Parolsh says which; #audit <n> still shows it.

A conversation the agent had elsewhere​

Parolsh's history only has what happened in Parolsh. A conversation you had with the agent in its own terminal, or in an editor, is the agent's: #sessions agent lists what the running agent has for this directory, and #resume agent <text> goes back to one.

[claude] ~/projects/wallet ✦ #sessions agent
· 2026-10-11 20:12 3062a1f0 Background task handling
· 2026-10-07 13:47 9b41c2de Background turns summary
14 2026-10-02 15:27 ef501917 Fix the crashing api
A dot: not in Parolsh's history. #resume agent <title or id> opens one.
[claude] ~/projects/wallet ✦ #resume agent task handling
…its last exchanges…
Resumed "Background task handling": the agent remembers that conversation.
It is session 33 from now on, with what the agent replayed of it.
  • Each line has when the conversation last changed, the start of the agent's id for it, and its title. The ones Parolsh has a session for show its number; #resume agent opens that session.
  • #resume agent <text> takes part of the title, in any case, or the start of the id. When several match, as two conversations with the same title do, it lists them: the id tells them apart. After a listing, Tab completes to the id.
  • It is recorded when it is opened. The agent replays the conversation (your messages, its answers, its tool calls), and Parolsh saves that as a new session: #redraw, #audit <n>, #sessions <text> and #resume <n> work on it like on any other. Only the conversation you open is taken, when you open it.
  • A replay has no dates: the session is dated when the agent says the conversation last changed, and its usage starts from now.
  • The running agent, for this directory. For another agent's, #agent <name> first. An agent that cannot replay a conversation only reopens it, and Parolsh says that it has nothing of what came before; one that does not list its conversations says so.
Not while it is open elsewhere

A conversation that is still open in the agent's own terminal would be written to by two programs. Parolsh cannot tell: close it there first.

Showing the conversation again​

#redraw, or Ctrl+L, clears the terminal and prints the last exchanges of the conversation again from the history, laid out for the terminal's width as it is now:

[claude] ~/projects/wallet ✦ why is the api container restarting?
• read: Read docker-compose.yml [docker-compose.yml] · completed
✦ The container exits because DATABASE_URL is not set: the entrypoint reads
it before the compose file's env_file is loaded.

turn ended · 18s
[claude] ~/projects/wallet ✦
  • Use it after resizing the window: what was already printed is not laid out again by itself (see During a turn).
  • An exchange is your message and what followed it. #redraw shows the last 5, #redraw 2 the last 2, and redraw_exchanges in the configuration changes the 5.
  • It shows your messages, the answers, and one line for each tool call, question, answer of yours and !+ output (its size, not its text).
  • The whole terminal is cleared, its scrollback too. The output of your earlier !commands goes with it: Parolsh does not keep it and cannot print it again.
  • Ctrl+L keeps the line you are typing.
  • In a conversation that is not saved (#new private, or history_days = 0) there is nothing to show again: it only clears.

The agent keeps conversations itself (Claude in ~/.claude/projects/): if it removed one, it cannot be resumed, and #audit <n> still shows what Parolsh saved:

parolsh: cannot resume session 11: the agent no longer has that conversation. #audit 11 shows what Parolsh saved of it

A session where you only ran shell commands has no conversation for the agent to go back to: an agent keeps one from its first message. #sessions names it by its first command, and #resume shows its commands and goes on with it, the agent starting a new conversation:

[claude] ~/projects/wallet ✦ #sessions
7 2026-10-03 15:38 claude 2 entries (commands only) !source .env
[claude] ~/projects/wallet ✦ #resume 7
!source .env · exit 0
!cd infra/ · exit 0
Continued session 7: it has only shell commands, so the agent starts a new conversation.

What the commands had set up is not there again: the directory your commands were in, and what they exported, are not saved.

A turn in the background​

A turn sent to the background with Ctrl+Z (see Turns in the background) leaves the session while it runs: its entries, from your message on, are a session of their own, which #sessions lists and #audit <n> shows. When the turn ends they go to the end of the session it left, where it ended, and that session of its own is gone. If the conversation it left was replaced meanwhile (#new, #cd, #agent, #resume), or you left Parolsh, it stays a session of its own, which #resume <n> can go back to.

Usage in the database​

For a report, what each turn used is in history.db, in the meta of the entry that ends it (kind = 'event', turn ended …), under usage:

FieldWhat
input, outputTokens sent to the model and received from it
thoughtReasoning tokens, for the agents that count them apart (Kilo Code)
cache_read, cache_writeTokens read from and written to the agent's cache
modelsThe models that answered
cost, currencyWhat the conversation cost since the turn before, when the agent says it
context, context_sizeThe tokens in the context after the turn, and its size
sqlite3 ~/.local/state/parolsh/history.db "
SELECT s.id, s.agent, sum(json_extract(e.meta, '\$.usage.input')) AS input,
sum(json_extract(e.meta, '\$.usage.output')) AS output,
round(sum(json_extract(e.meta, '\$.usage.cost')), 2) AS cost
FROM sessions s JOIN entries e ON e.session_id = s.id
WHERE e.kind = 'event' GROUP BY s.id"

A turn the agent starts by itself, after a background task, reports no tokens: its cost is counted with the next turn you send. A compaction is its own entry, with compaction.before and compaction.after.

The agent can search the history​

In every conversation that is saved, the agent gets the history of this project as an MCP server, parolsh-history, so it can look up earlier work itself when you refer to it, without loading whole sessions:

[claude] ~/projects/wallet ✦ how did we fix the retries last week?
• mcp__parolsh-history__search_history
Last Tuesday we added exponential backoff in src/client.rs …
ToolWhat it returns
search_historyThe best matches for some words (SQLite FTS5: retry OR backoff, "a phrase", prefix*), with the session and entry
list_sessionsThe sessions: number, date, agent, title
get_sessionThe entries of one session, a page at a time, with their full text
commandsThe saved shell commands and their exit codes

Ask in your own words; the agent picks the tool:

You askThe agent uses
where did we change the retry logic?search_history
summarize session #2get_session, with the number #sessions shows
what did we work on last week?list_sessions, then get_session
which commands failed today?commands (!+ ones; plain !command lines only with commands = "shared")
[claude] ~/projects/wallet ✦ summarize session #2
• mcp__parolsh-history__get_session
Session #2 was about the billing rewrite, codename Falcon-9 …
  • Start the line with a word, not with #: #2 summarize is a Parolsh command.
  • The search matches words, not meanings. For something exact, give the words: search the history for Falcon-9.
  • If the agent answers without looking, name the tools: use the parolsh-history tools to find …. Claude, Codex, Kilo Code and OpenCode used the tools when asked to search the history; Qwen Code and Goose searched the files instead, and used them once they were named. Kilo and Qwen ask before each call, like for any tool.

The server is Parolsh itself (parolsh mcp), started by the agent. It reads the history without changing it, and its tools only return this project's sessions, and those of other projects you shared with the conversation: they cannot ask for another. A #new private conversation does not get it. To see what the tools return without the agent, see Asking the history yourself.

Sharing a session of another project​

The agent's tools only return this project's sessions. For one of another project, the tool says so, and the agent tells you:

[claude] ~/projects/site ✦ can you summarize session 7?
✦ I can't read it: session 7 belongs to another project and hasn't been shared
here. Type #share 7 at the Parolsh prompt and I'll check it.
[claude] ~/projects/site ✦ #share 7
Session 7: "Inotify limit validation", ~, 2026-10-04 11:30.
The agent of this conversation can now read it with its history tools.
[claude] ~/projects/site ✦ try again
  • The agent reads it as it reads this project's sessions, a page at a time, and its search covers it. Parolsh puts nothing of it in the conversation.
  • For this conversation only: a new one (#new, #cd, #agent, #resume) starts without it. The conversation that goes on after a turn was sent to the background keeps it.
  • Your !command lines of that session are left out, as this project's are, unless commands = "shared".
  • #share alone lists what is shared. #sessions all finds the session's number, and #audit <n> shows it to you without giving it to the agent.
  • Not in a #new private conversation, nor with the history off: the agent has no history tools there.