Add security hardening, Ghidra, recreate skill, checkpoints, shells, web search and themes
- Sandbox (bubblewrap) for non-admin shell/git, MCP per-user rights, hard budgets and quotas, login rate limiting, audit log and backups - Ghidra headless decompilation (ARM64 natives built from source), binary_info tool, clean room / deep workflow per session - Recreate skill and commands for analysing and re-building old software - File checkpoints with rewind/restore, background shells (bash_output, kill_shell) - web_search tool (DuckDuckGo, SearXNG, Brave, Tavily) - In-app dialogs and toasts instead of browser dialogs - 15 base themes (trilium-themes palettes plus Nord, VS Code, GitHub, Catppuccin, One, Dracula, Rose Pine, Everforest, Kanagawa) with light/dark/auto switcher and license notes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
fab9add5d5
commit
5b569b6835
108 files changed
+6785
-279
No files matched your search
+38
-13
@@ -24,7 +24,9 @@ impl Tool for Bash {
|
||||
"Run a shell command (bash) in the session working directory. stdout and stderr are \
|
||||
combined. Default timeout 2 minutes, max 10 minutes (timeout_ms). The working directory \
|
||||
does not persist between calls – use absolute paths or `cd dir && ...`. Prefer the \
|
||||
dedicated read/edit/glob/grep tools over cat/sed/find/grep."
|
||||
dedicated read/edit/glob/grep tools over cat/sed/find/grep. For long-running processes \
|
||||
(dev servers, watchers, long builds) set run_in_background=true: you get a shell id, \
|
||||
read new output with bash_output and stop it with kill_shell."
|
||||
.into()
|
||||
}
|
||||
fn schema(&self) -> Value {
|
||||
@@ -33,7 +35,8 @@ impl Tool for Bash {
|
||||
"properties": {
|
||||
"command": {"type": "string"},
|
||||
"description": {"type": "string", "description": "5-10 word description of what the command does"},
|
||||
"timeout_ms": {"type": "integer"}
|
||||
"timeout_ms": {"type": "integer"},
|
||||
"run_in_background": {"type": "boolean", "description": "Keep running; read output with bash_output"}
|
||||
},
|
||||
"required": ["command"]
|
||||
})
|
||||
@@ -49,17 +52,18 @@ impl Tool for Bash {
|
||||
let timeout = Duration::from_millis(
|
||||
input["timeout_ms"].as_u64().unwrap_or(DEFAULT_TIMEOUT_MS).min(MAX_TIMEOUT_MS),
|
||||
);
|
||||
let mut cmd = Command::new("bash");
|
||||
cmd.arg("-c")
|
||||
.arg(format!("{command} 2>&1"))
|
||||
.current_dir(&ctx.cwd)
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::null())
|
||||
.env("CODECRAFT", "1")
|
||||
.env("GIT_TERMINAL_PROMPT", "0")
|
||||
.env("PAGER", "cat")
|
||||
.kill_on_drop(true);
|
||||
let mut cmd = match shell_command(ctx, command) {
|
||||
Ok(c) => c,
|
||||
Err(e) => return Ok(e),
|
||||
};
|
||||
if input["run_in_background"].as_bool().unwrap_or(false) {
|
||||
let id = crate::shells::spawn(&ctx.app, &ctx.session_id, command, cmd)?;
|
||||
return Ok(ToolOutput::text(format!(
|
||||
"Started in the background with shell id {id}. Read its output with bash_output (shell_id \"{id}\") and stop it with kill_shell."
|
||||
))
|
||||
.with_meta(json!({"shell_id": id})));
|
||||
}
|
||||
cmd.stdin(Stdio::null()).stdout(Stdio::piped()).stderr(Stdio::null()).kill_on_drop(true);
|
||||
// Own process group so the whole tree can be killed on abort/timeout.
|
||||
cmd.process_group(0);
|
||||
let mut child = cmd.spawn()?;
|
||||
@@ -128,6 +132,27 @@ impl Tool for Bash {
|
||||
}
|
||||
}
|
||||
|
||||
/// The bash command for a script, sandboxed for non-admin users.
|
||||
pub fn shell_command(ctx: &ToolCtx, command: &str) -> std::result::Result<Command, ToolOutput> {
|
||||
// stderr of every command (not just the last one) goes into the output.
|
||||
let script = format!("exec 2>&1\n{command}");
|
||||
Ok(match &ctx.sandbox {
|
||||
Some(spec) => {
|
||||
if !crate::sandbox::available() {
|
||||
return Err(ToolOutput::error(
|
||||
"Shell commands are disabled for this account: the server's sandbox (bubblewrap) is not available. Ask an admin.",
|
||||
));
|
||||
}
|
||||
crate::sandbox::command(spec, &ctx.cwd, "bash", &["-c", &script])
|
||||
}
|
||||
None => {
|
||||
let mut c = Command::new("bash");
|
||||
c.arg("-c").arg(&script).current_dir(&ctx.cwd).env("CODECRAFT", "1").env("GIT_TERMINAL_PROMPT", "0").env("PAGER", "cat");
|
||||
c
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn tail(s: &str, max: usize) -> String {
|
||||
if s.len() <= max {
|
||||
return s.to_string();
|
||||
|
||||
Reference in new issue
Block a user