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, see Text
?textThe active ACP agent
/commandThe active ACP agent, unchanged, see Agent slash commands
!commandThe configured shell, default bash -ic, see Shell commands
!+commandThe same, and its output goes with your next message, see Sharing a command's output
!bashAn interactive Bash session, see Interactive Bash
#commandParolsh itself, see Parolsh commands
! 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. Tab still completes the agent's commands there, see Tab completion
!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 Shell commands). 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. The arguments of the other # commands are not completed, including those that take one: #agent <name>, #pair <agent>, #prompt <name>, #share <n>.

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 Agent slash commands. Other words of the text have no completion.

In shell mode a plain line that starts with / runs as a shell command, but Tab there still completes the agent's commands, not paths: /usr/bi<Tab> offers the agent's list. Type !/usr/bi<Tab> to complete the path.

Shell commands​

!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. There they are set before its startup files run, so a variable your ~/.bashrc sets again (a PATH it adds to) takes its value from ~/.bashrc. 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 project stays too: a cd does not look for .parolsh/ again, so its configuration is still that of the agent's directory until #cd (see Projects).

  • 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"]

Sharing a command's output​

!+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.

Interactive Bash​

!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​

In agent mode, a line that does not start with ! or # goes to the agent (in shell mode, start it with ?): text is a question, and a line that starts with / is one of the agent's commands. 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.

Agent slash commands​

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.

Parolsh commands​

Lines starting with # are Parolsh's own commands; #help lists them.

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, #agent or #resume
#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. The agent in use stays when that project configures it, which agents defined in the global file always are, even if the project's default_agent names another; only when it is not configured there does the project's default_agent take over. The agent restarts when its settings (mode, options) differ there.
#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 for the running agent process; a new process takes the configuration's again, see Options
#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 Parolsh's directory, the agent's: after a cd moved your commands away, not the one they are in. See Projects
#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
#pair <agent>Pair with a second agent: your next message is the issue, for both, and it answers what the agent says when it stops, once you agree. See Pairing two agents
#pair <agent> <text>Ask the second agent something of its own ("review the tests"): the agent is not sent it, and the second agent starts at once with what the agent answered last
#pair [off]Show the second agent, or stop pairing
#decideAsk the second agent again about what the agent said last
#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.

Moved sections​

Sessions and history have a page of their own. The sections that were here: