mirror of
https://github.com/khodges42/exoshell.git
synced 2026-06-14 18:08:37 +00:00
Quickstart
This commit is contained in:
parent
c552a93a9a
commit
40216fb635
|
|
@ -6,6 +6,8 @@ A cognitive shell for engineers who still want the controls.
|
|||
|
||||
Exoshell is a local-first, shell-adjacent assistant for practitioners who want AI help without giving up operational awareness or control. The shell remains primary; Exoshell suggests, explains, preserves context, and keeps the human in the loop. Exoshell is not designed for “vibe coding.”
|
||||
|
||||
Start here: [Quickstart and Tour](docs/quickstart.md).
|
||||
|
||||
For the full project philosophy and design direction, read [docs/DESIGN.md](docs/DESIGN.md).
|
||||
|
||||
## Philosophy
|
||||
|
|
|
|||
268
docs/quickstart.md
Normal file
268
docs/quickstart.md
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
# Quickstart
|
||||
|
||||
This guide gets Exoshell running and shows the main Phase 2 workflow.
|
||||
|
||||
Exoshell suggests commands and explains system work. It does not execute commands.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Install a current Rust toolchain with `rustup`.
|
||||
|
||||
```sh
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o /tmp/rustup-init.sh
|
||||
sh /tmp/rustup-init.sh -y --profile default --default-toolchain stable
|
||||
. "$HOME/.cargo/env"
|
||||
```
|
||||
|
||||
Check the toolchain:
|
||||
|
||||
```sh
|
||||
cargo --version
|
||||
rustc --version
|
||||
rustfmt --version
|
||||
```
|
||||
|
||||
On Ubuntu or WSL, provider dependencies may also need:
|
||||
|
||||
```sh
|
||||
sudo apt update
|
||||
sudo apt install pkg-config libssl-dev
|
||||
```
|
||||
|
||||
## Configure a Provider
|
||||
|
||||
For OpenAI-compatible hosted providers, set an API key:
|
||||
|
||||
```sh
|
||||
export OPENAI_API_KEY="..."
|
||||
```
|
||||
|
||||
For a local OpenAI-compatible provider, create a config file:
|
||||
|
||||
```toml
|
||||
[provider]
|
||||
base_url = "http://localhost:11434/v1"
|
||||
model = "local-model"
|
||||
request_timeout_seconds = 120
|
||||
|
||||
[shell]
|
||||
family = "posix"
|
||||
|
||||
[interaction]
|
||||
stance = "operator"
|
||||
```
|
||||
|
||||
Local provider URLs such as `localhost` and `127.0.0.1` do not require an API key.
|
||||
|
||||
## Start Exoshell
|
||||
|
||||
Run with defaults:
|
||||
|
||||
```sh
|
||||
cargo run
|
||||
```
|
||||
|
||||
Run with a config file:
|
||||
|
||||
```sh
|
||||
cargo run -- --config path/to/config.toml
|
||||
```
|
||||
|
||||
Select a shell family:
|
||||
|
||||
```sh
|
||||
cargo run -- --shell posix
|
||||
cargo run -- --shell powershell
|
||||
```
|
||||
|
||||
Select an operating stance:
|
||||
|
||||
```sh
|
||||
cargo run -- --stance audit
|
||||
```
|
||||
|
||||
## First Session
|
||||
|
||||
At the prompt:
|
||||
|
||||
```text
|
||||
exo> /help
|
||||
```
|
||||
|
||||
Attach a note as explicit context:
|
||||
|
||||
```text
|
||||
exo> /add-note this repo is a Rust CLI called Exoshell
|
||||
```
|
||||
|
||||
Inspect context:
|
||||
|
||||
```text
|
||||
exo> /context
|
||||
exo> /context stats
|
||||
```
|
||||
|
||||
Ask a question:
|
||||
|
||||
```text
|
||||
exo> What should I inspect before changing command parsing?
|
||||
```
|
||||
|
||||
Exoshell may return suggested commands in fenced shell blocks. Suggested commands are reviewable text. You decide whether to copy and run them in your shell.
|
||||
|
||||
## Context Tour
|
||||
|
||||
Context is explicit and session-scoped. Exoshell only sends enabled context to the model.
|
||||
|
||||
Add a file:
|
||||
|
||||
```text
|
||||
exo> /add-file Cargo.toml
|
||||
```
|
||||
|
||||
Add a shallow directory summary:
|
||||
|
||||
```text
|
||||
exo> /add-dir src
|
||||
```
|
||||
|
||||
Paste command output without Exoshell running the command:
|
||||
|
||||
```text
|
||||
exo> /add-output
|
||||
paste command output; finish with a single '.' line
|
||||
... test result: ok
|
||||
... .
|
||||
```
|
||||
|
||||
Inspect one entry:
|
||||
|
||||
```text
|
||||
exo> /context show ctx-001
|
||||
```
|
||||
|
||||
Control inclusion:
|
||||
|
||||
```text
|
||||
exo> /context disable ctx-001
|
||||
exo> /context enable ctx-001
|
||||
```
|
||||
|
||||
Control pruning preference:
|
||||
|
||||
```text
|
||||
exo> /context pin ctx-001
|
||||
exo> /context priority ctx-001 high
|
||||
```
|
||||
|
||||
Remove an entry:
|
||||
|
||||
```text
|
||||
exo> /context remove ctx-001
|
||||
```
|
||||
|
||||
## Stance Tour
|
||||
|
||||
Stances change the compact behavior fragment in the prompt.
|
||||
|
||||
Show the current stance:
|
||||
|
||||
```text
|
||||
exo> /stance
|
||||
```
|
||||
|
||||
Switch stance:
|
||||
|
||||
```text
|
||||
exo> /stance operator
|
||||
exo> /stance audit
|
||||
exo> /stance teach
|
||||
exo> /stance quiet
|
||||
```
|
||||
|
||||
Use `operator` for concise next steps, `audit` for risk review, `teach` for fuller explanations, and `quiet` for minimal prose.
|
||||
|
||||
## Command Suggestion Tour
|
||||
|
||||
When a model response includes shell fenced blocks, Exoshell assigns command IDs such as `cmd-001`.
|
||||
|
||||
Print a suggested command:
|
||||
|
||||
```text
|
||||
exo> /copy cmd-001
|
||||
```
|
||||
|
||||
Clipboard support is not implemented yet, so `/copy` prints the command. It does not execute it.
|
||||
|
||||
Explain a suggestion:
|
||||
|
||||
```text
|
||||
exo> /explain cmd-001
|
||||
```
|
||||
|
||||
Discard a suggestion:
|
||||
|
||||
```text
|
||||
exo> /discard cmd-001
|
||||
```
|
||||
|
||||
Risk warnings are heuristic. Treat a warning as a prompt for careful review. Lack of a warning does not prove a command is safe.
|
||||
|
||||
## Session Panel
|
||||
|
||||
Show the current operating state:
|
||||
|
||||
```text
|
||||
exo> /panel
|
||||
```
|
||||
|
||||
The panel includes stance, shell family, provider/model, transcript state, context entries, and prompt estimates.
|
||||
|
||||
## Multi-Line Prompts
|
||||
|
||||
Use `/multi` for longer prompts:
|
||||
|
||||
```text
|
||||
exo> /multi
|
||||
multi-line input; finish with a single '.' line
|
||||
... Review this plan:
|
||||
... 1. Add parser tests.
|
||||
... 2. Refactor command rendering.
|
||||
... .
|
||||
```
|
||||
|
||||
## Piped Input
|
||||
|
||||
Pipe text into Exoshell as explicit context:
|
||||
|
||||
```sh
|
||||
printf 'build failed in openssl-sys\n' | cargo run
|
||||
```
|
||||
|
||||
Exoshell records piped content as user-provided context. It does not claim to know the upstream command unless you provide that separately.
|
||||
|
||||
## Quality Checks
|
||||
|
||||
Run:
|
||||
|
||||
```sh
|
||||
cargo fmt --check
|
||||
cargo test
|
||||
cargo clippy --all-targets --all-features
|
||||
```
|
||||
|
||||
If `cargo test` fails on Ubuntu or WSL with an OpenSSL or `pkg-config` error, install:
|
||||
|
||||
```sh
|
||||
sudo apt install pkg-config libssl-dev
|
||||
```
|
||||
|
||||
## Exit
|
||||
|
||||
Quit the REPL:
|
||||
|
||||
```text
|
||||
exo> /exit
|
||||
```
|
||||
|
||||
If transcripts are enabled, Exoshell writes a markdown transcript at shutdown.
|
||||
10
src/app.rs
10
src/app.rs
|
|
@ -368,7 +368,8 @@ impl App {
|
|||
if let Some(warning) = suggestion.detected_risk.warning() {
|
||||
explanation.push_str(&format!("{warning}\n"));
|
||||
} else {
|
||||
explanation.push_str("No obvious destructive pattern was detected. Review before running.\n");
|
||||
explanation
|
||||
.push_str("No obvious destructive pattern was detected. Review before running.\n");
|
||||
}
|
||||
self.transcript
|
||||
.record_command_action(id, "explain", "operator requested explanation");
|
||||
|
|
@ -577,10 +578,11 @@ impl CliOptions {
|
|||
let value = args.next().ok_or_else(|| {
|
||||
crate::config::ConfigError::Invalid("--stance requires a value".into())
|
||||
})?;
|
||||
options.stance =
|
||||
Some(value.parse().map_err(|error: crate::prompts::StanceError| {
|
||||
options.stance = Some(value.parse().map_err(
|
||||
|error: crate::prompts::StanceError| {
|
||||
crate::config::ConfigError::Invalid(error.to_string())
|
||||
})?);
|
||||
},
|
||||
)?);
|
||||
}
|
||||
"--no-transcript" => options.transcript_enabled = Some(false),
|
||||
"--transcript-dir" => {
|
||||
|
|
|
|||
|
|
@ -63,10 +63,7 @@ impl CommandRisk {
|
|||
if self.reasons.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(format!(
|
||||
"review required: {}",
|
||||
self.reasons.join("; ")
|
||||
))
|
||||
Some(format!("review required: {}", self.reasons.join("; ")))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -132,7 +129,9 @@ pub fn detect_command_risk(command: &str, shell: CommandShell) -> CommandRisk {
|
|||
|
||||
if lowered.contains("rm -rf")
|
||||
|| lowered.contains("rm -fr")
|
||||
|| lowered.contains("remove-item") && lowered.contains("-recurse") && lowered.contains("-force")
|
||||
|| lowered.contains("remove-item")
|
||||
&& lowered.contains("-recurse")
|
||||
&& lowered.contains("-force")
|
||||
|| lowered.contains("del /s")
|
||||
{
|
||||
reasons.push("recursive or forced deletion".into());
|
||||
|
|
@ -200,7 +199,11 @@ pub fn render_suggestions(suggestions: &[CommandSuggestion]) -> String {
|
|||
"- {} [{}]{}",
|
||||
suggestion.id,
|
||||
suggestion.shell,
|
||||
if suggestion.discarded { " discarded" } else { "" }
|
||||
if suggestion.discarded {
|
||||
" discarded"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
));
|
||||
if let Some(risk) = suggestion.model_risk {
|
||||
rendered.push_str(&format!(" model_risk={risk}"));
|
||||
|
|
@ -210,7 +213,9 @@ pub fn render_suggestions(suggestions: &[CommandSuggestion]) -> String {
|
|||
}
|
||||
rendered.push('\n');
|
||||
}
|
||||
rendered.push_str("Use /copy <id>, /explain <id>, or /discard <id>. Exoshell does not execute commands.");
|
||||
rendered.push_str(
|
||||
"Use /copy <id>, /explain <id>, or /discard <id>. Exoshell does not execute commands.",
|
||||
);
|
||||
rendered
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -236,7 +236,10 @@ enum TranscriptEntry {
|
|||
note: String,
|
||||
},
|
||||
BudgetWarning(String),
|
||||
StanceChange { previous: String, current: String },
|
||||
StanceChange {
|
||||
previous: String,
|
||||
current: String,
|
||||
},
|
||||
CommandSuggestion {
|
||||
id: String,
|
||||
shell: String,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user