Repository navigation
feat(cli): send rich context with shelltime q - #315
Merged
Merged
Conversation
ClassifyCommand only looked at the first word, so with ai.agent.view enabled `curl ... | sh`, `ls | xargs rm -rf` or `cat a; rm -rf ~` were auto-run as "view". `shelltime q` is about to send repository-controlled text (file names, commit subjects, script names) to the model, so the classifier has to be safe against a manipulated suggestion. - Split pipelines, lists and substitutions (quote and escape aware) and return the most severe segment. - Treat interpreters and wrappers (sh, python, xargs, sudo, eval, env with a command, find -exec, ...) and multi-line scripts as "other", which never auto-runs. - Upgrade view commands that redirect output to a file, and downloads (curl -o, wget), to "edit". - Classify git, docker/podman, kubectl and systemctl by subcommand: read-only subcommands stay "view", `git reset --hard`, forced pushes, branch/stash deletion and `kubectl delete` are "delete", and exec, reboot and global git options are "other". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012gybkwT4DrTkNF4wKq54JT
`shelltime q` only sent the shell, OS, working directory and hostname, so suggestions guessed at the repository, project tooling and machine. When ai.shareContext is enabled (the default) it now also sends a `context` object, collected concurrently within 500ms: - system: OS version, kernel, arch, CPU count, uptime, load average, root, SSH, container, multiplexer, terminal, timezone and local time (read from /proc and sysctl, no forks) - git: path in repo, branch, upstream, ahead/behind, staged, unstaged, untracked and conflicted counts, in-progress operation, remote hosts and the last 3 commit subjects; falls back to HEAD if `git status` is slow - project: types and package managers from manifest and lock files, walking up to the repo root for monorepos, plus package.json script, Makefile target and justfile recipe names - tools found on PATH, and up to 40 names from the current directory The shell is now taken from the parent process when it is a known shell, so a fish session started from a zsh login shell is reported as fish. `shelltime q --show-context "..."` prints the request without calling the AI. With ai.shareContext: false only shell, OS and query are sent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012gybkwT4DrTkNF4wKq54JT
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Codecov Report❌ Patch coverage is
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 4 files with indirect coverage changes 🚀 New features to boost your workflow:
|
- classifyDocker, classifyKubectl and classifySystemctl read the first argument as the subcommand, so `kubectl -n prod delete pod web`, `docker --context x rm -f web` or `systemctl --force poweroff` fell through to "edit" and auto-ran with ai.agent.edit. A leading global option now classifies as "other" (never auto-run), as git already did. - ParseJustRecipes indexed fields[0] on lines made only of non-ASCII whitespace (\v, \f, NBSP), panicking inside a collector goroutine and crashing `shelltime q`. Skip such lines. - Recover panics in query context collectors so a collector bug can only drop that piece of context. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012gybkwT4DrTkNF4wKq54JT
Contributor
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
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.
Summary
shelltime qsent only the shell, OS, working directory and hostname, so the model had to guess about the repository, project tooling and machine. Withai.shareContexton (the default), it now also sends a boundedcontextobject that makes suggestions fit the user's real environment.Server side: https://github.com/shelltime/server/pull/505. Today the server drops everything except shell, OS and query, so deploy that PR first. This CLI change is harmless against an old server, which ignores unknown fields.
Context collected
Five collectors run concurrently under a 500 ms limit (git gets 400 ms). Anything late is dropped. A dry run takes about 30 ms in a 1,600-file repo.
TERM_PROGRAM, timezone, local time. Read from/procand/etc/os-releaseon Linux and from sysctl on macOS, with no forks.name=hostonly, last 3 commit subjects. Ifgit statusis too slow, the branch is read fromHEADandstatusIncompleteis set.packageManagerfield wins. Alsopackage.jsonscript names, Makefile targets and justfile recipes (names only, common ones first, max 20).PATH(rg,fd,jq,docker,pnpm,brew, …), plus GNU variants such asgsedon macOS./on directories. Skipped in$HOME.Also:
$SHELL. A fish session started from a zsh login shell now reportsfish.shelltime q --show-context "…": prints the request as JSON on stdout (pipeable tojq) without calling the AI or spending credits. It works without a token.ai.shareContext: falsesends only shell, OS and query.golang.org/x/sysis promoted from indirect to direct (no new module).sysstat_{linux,darwin,other}.gokeep the Windows build working.Auto-run hardening (separate commit)
The prompt now carries text the repository author controls (file names, commit subjects, script names). Before this PR,
ClassifyCommandlooked only at the first word, so withai.agent.viewon,curl … | sh,ls | xargs rm -rforcat a; rm -rf ~would auto-run as "view". Now:sh,python,xargs,sudo,eval,env cmd,find -exec, …) and multi-line scripts are classed as "other", which never auto-runs.curl -oandwgetare classed as "edit".git reset --hard, force push, branch or stash deletion andkubectl deleteare delete;docker execandsystemctl rebootare other.Docs
docs/CONFIG.mddocumentsshareContext, the table of what is sent,--show-context, the server-side AI Context, a privacy note and the compound-command auto-run rules.README.mdlinks to it.Testing
/procand darwinvm.loadavg; Makefile, justfile and package.json fixtures underfixtures/query_context/; monorepo walk-up, including that manifests above the repo root are ignored; directory listing and truncation; sanitizer (ANSI, control characters, rune-safe truncation); 60+ new classifier cases.shareContext: falseskips collection and sends no context;--show-contextis a dry run, including without an AI service; shell detection; a real end-to-endgatherQueryContextin a temp pnpm repo.go vet ./...passes on linux and darwin; darwin and windows (amd64/arm64) builds pass.go test -timeout 3m -coverprofile=coverage.txt -covermode=atomic ./...) passes.go test -racepasses forcommandsandmodeland for the new daemon tests. The fulldaemonpackage has intermittent-racefailures in existing tests (TestSocketTopicProcessor_TrackPreAndPostRouted,TestCCInfoTimerTestSuite,TestFetchRateLimit_…) that also reproduce onmainwithout this change. CI doesn't run-race.🤖 Generated with Claude Code
https://claude.ai/code/session_012gybkwT4DrTkNF4wKq54JT
Generated by Claude Code