dsh-ops 0.0.0-stage → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/CHANGELOG.md +189 -0
  2. package/LICENSE +30 -0
  3. package/NOTICE +106 -0
  4. package/PROVENANCE.md +417 -0
  5. package/README.en.md +121 -0
  6. package/README.md +113 -2
  7. package/README.zh.md +114 -0
  8. package/bin/dsh-ops.mjs +1216 -0
  9. package/cordis.patch.yml +160 -0
  10. package/docs/manual-validation.md +53 -0
  11. package/docs/schema-baseline.json +64 -0
  12. package/docs/schema-current.json +84 -0
  13. package/docs/schema-measurement.md +17 -0
  14. package/dsh-plugin.json +88 -0
  15. package/icon.svg +12 -0
  16. package/lib/binary.js +409 -0
  17. package/lib/config.js +198 -0
  18. package/lib/handshake.js +252 -0
  19. package/lib/index.js +108 -0
  20. package/lib/jobs.js +42 -0
  21. package/lib/policy.js +64 -0
  22. package/lib/presentation.js +63 -0
  23. package/lib/profile-install.js +61 -0
  24. package/lib/rust.js +194 -0
  25. package/lib/session-shells.js +78 -0
  26. package/lib/shells.js +993 -0
  27. package/lib/tools.js +657 -0
  28. package/locale/en.json +6 -0
  29. package/locale/zh.json +6 -0
  30. package/package.json +114 -4
  31. package/vendor/fastctx/Cargo.lock +3210 -0
  32. package/vendor/fastctx/Cargo.toml +94 -0
  33. package/vendor/fastctx/FORK.md +119 -0
  34. package/vendor/fastctx/LICENSE-APACHE +201 -0
  35. package/vendor/fastctx/NOTICE +40 -0
  36. package/vendor/fastctx/README.md +439 -0
  37. package/vendor/fastctx/THIRD_PARTY_LICENSES.md +17 -0
  38. package/vendor/fastctx/THIRD_PARTY_LICENSES_RUST.md +7914 -0
  39. package/vendor/fastctx/UPSTREAM.md +49 -0
  40. package/vendor/fastctx/build.rs +413 -0
  41. package/vendor/fastctx/src/background_status.rs +403 -0
  42. package/vendor/fastctx/src/binary.rs +75 -0
  43. package/vendor/fastctx/src/bounded_sort.rs +500 -0
  44. package/vendor/fastctx/src/budget.rs +781 -0
  45. package/vendor/fastctx/src/cli/mod.rs +110 -0
  46. package/vendor/fastctx/src/context_guard.rs +289 -0
  47. package/vendor/fastctx/src/control/mod.rs +6 -0
  48. package/vendor/fastctx/src/control/paths.rs +49 -0
  49. package/vendor/fastctx/src/control/settings.rs +753 -0
  50. package/vendor/fastctx/src/control/transaction.rs +531 -0
  51. package/vendor/fastctx/src/edit/document.rs +535 -0
  52. package/vendor/fastctx/src/edit/locks.rs +371 -0
  53. package/vendor/fastctx/src/edit/mod.rs +213 -0
  54. package/vendor/fastctx/src/edit/private_storage/unix.rs +315 -0
  55. package/vendor/fastctx/src/edit/private_storage/windows.rs +793 -0
  56. package/vendor/fastctx/src/edit/private_storage.rs +234 -0
  57. package/vendor/fastctx/src/edit/replace.rs +1030 -0
  58. package/vendor/fastctx/src/edit_server.rs +53 -0
  59. package/vendor/fastctx/src/encoding/reference_v011.rs +587 -0
  60. package/vendor/fastctx/src/encoding/snapshot_pipeline.rs +1678 -0
  61. package/vendor/fastctx/src/encoding.rs +1118 -0
  62. package/vendor/fastctx/src/file_executor.rs +1151 -0
  63. package/vendor/fastctx/src/file_snapshot.rs +1491 -0
  64. package/vendor/fastctx/src/glob_filter.rs +98 -0
  65. package/vendor/fastctx/src/glob_tool.rs +653 -0
  66. package/vendor/fastctx/src/grep_sink.rs +1162 -0
  67. package/vendor/fastctx/src/grep_tool.rs +2449 -0
  68. package/vendor/fastctx/src/lib.rs +45 -0
  69. package/vendor/fastctx/src/main.rs +15 -0
  70. package/vendor/fastctx/src/model.rs +51 -0
  71. package/vendor/fastctx/src/model_guidance.rs +62 -0
  72. package/vendor/fastctx/src/operation.rs +356 -0
  73. package/vendor/fastctx/src/ordered_window.rs +1235 -0
  74. package/vendor/fastctx/src/os_environment.rs +414 -0
  75. package/vendor/fastctx/src/path_codec.rs +850 -0
  76. package/vendor/fastctx/src/paths.rs +244 -0
  77. package/vendor/fastctx/src/process_identity.rs +763 -0
  78. package/vendor/fastctx/src/process_policy.rs +74 -0
  79. package/vendor/fastctx/src/read_tool/batch.rs +496 -0
  80. package/vendor/fastctx/src/read_tool/hex_file.rs +141 -0
  81. package/vendor/fastctx/src/read_tool/image_file.rs +88 -0
  82. package/vendor/fastctx/src/read_tool/mod.rs +245 -0
  83. package/vendor/fastctx/src/read_tool/pdf.rs +470 -0
  84. package/vendor/fastctx/src/read_tool/pdf_disabled.rs +47 -0
  85. package/vendor/fastctx/src/read_tool/pdf_engine.rs +664 -0
  86. package/vendor/fastctx/src/read_tool/text_file.rs +351 -0
  87. package/vendor/fastctx/src/render_plan.rs +468 -0
  88. package/vendor/fastctx/src/runtime/activity.rs +159 -0
  89. package/vendor/fastctx/src/runtime/hosts.rs +99 -0
  90. package/vendor/fastctx/src/runtime/journal.rs +556 -0
  91. package/vendor/fastctx/src/runtime/local_ipc.rs +186 -0
  92. package/vendor/fastctx/src/runtime/mod.rs +746 -0
  93. package/vendor/fastctx/src/runtime/protocol.rs +296 -0
  94. package/vendor/fastctx/src/runtime/session.rs +536 -0
  95. package/vendor/fastctx/src/runtime/windows_process.rs +66 -0
  96. package/vendor/fastctx/src/search_parallelism.rs +106 -0
  97. package/vendor/fastctx/src/search_text.rs +227 -0
  98. package/vendor/fastctx/src/server.rs +359 -0
  99. package/vendor/fastctx/src/server_manifest.rs +468 -0
  100. package/vendor/fastctx/src/server_support.rs +826 -0
  101. package/vendor/fastctx/src/session.rs +629 -0
  102. package/vendor/fastctx/src/shell/apply_patch_hint.rs +41 -0
  103. package/vendor/fastctx/src/shell/bash.rs +263 -0
  104. package/vendor/fastctx/src/shell/buffer.rs +108 -0
  105. package/vendor/fastctx/src/shell/encoding.rs +403 -0
  106. package/vendor/fastctx/src/shell/foreground.rs +115 -0
  107. package/vendor/fastctx/src/shell/jobs/admission.rs +91 -0
  108. package/vendor/fastctx/src/shell/jobs/background.rs +146 -0
  109. package/vendor/fastctx/src/shell/jobs/host.rs +830 -0
  110. package/vendor/fastctx/src/shell/jobs/identity.rs +29 -0
  111. package/vendor/fastctx/src/shell/jobs/mod.rs +1513 -0
  112. package/vendor/fastctx/src/shell/jobs/model.rs +244 -0
  113. package/vendor/fastctx/src/shell/jobs/output_log.rs +1148 -0
  114. package/vendor/fastctx/src/shell/jobs/store.rs +1300 -0
  115. package/vendor/fastctx/src/shell/mod.rs +345 -0
  116. package/vendor/fastctx/src/shell/normalize.rs +389 -0
  117. package/vendor/fastctx/src/shell/output.rs +406 -0
  118. package/vendor/fastctx/src/shell/process.rs +493 -0
  119. package/vendor/fastctx/src/shell_server.rs +156 -0
  120. package/vendor/fastctx/src/skip_report.rs +83 -0
  121. package/vendor/fastctx/src/stdio_transport.rs +177 -0
  122. package/vendor/fastctx/src/tool_schema.rs +204 -0
  123. package/vendor/fastctx/src/traversal.rs +846 -0
  124. package/vendor/fastctx/third-party/pdfium-7763/LICENSE +9 -0
  125. package/vendor/fastctx/third-party/pdfium-7763/licenses/abseil.txt +202 -0
  126. package/vendor/fastctx/third-party/pdfium-7763/licenses/agg23.txt +14 -0
  127. package/vendor/fastctx/third-party/pdfium-7763/licenses/fast_float.txt +27 -0
  128. package/vendor/fastctx/third-party/pdfium-7763/licenses/freetype.txt +169 -0
  129. package/vendor/fastctx/third-party/pdfium-7763/licenses/icu.txt +542 -0
  130. package/vendor/fastctx/third-party/pdfium-7763/licenses/lcms.txt +27 -0
  131. package/vendor/fastctx/third-party/pdfium-7763/licenses/libjpeg_turbo.ijg +260 -0
  132. package/vendor/fastctx/third-party/pdfium-7763/licenses/libjpeg_turbo.md +135 -0
  133. package/vendor/fastctx/third-party/pdfium-7763/licenses/libopenjpeg.txt +32 -0
  134. package/vendor/fastctx/third-party/pdfium-7763/licenses/libpng.txt +134 -0
  135. package/vendor/fastctx/third-party/pdfium-7763/licenses/libtiff.txt +21 -0
  136. package/vendor/fastctx/third-party/pdfium-7763/licenses/llvm-libc.txt +278 -0
  137. package/vendor/fastctx/third-party/pdfium-7763/licenses/pdfium.txt +230 -0
  138. package/vendor/fastctx/third-party/pdfium-7763/licenses/simdutf.txt +18 -0
  139. package/vendor/fastctx/third-party/pdfium-7763/licenses/zlib.txt +29 -0
@@ -0,0 +1,439 @@
1
+ # FastCtx
2
+
3
+ **English** | [简体中文](./README.zh-CN.md)
4
+
5
+ ### Fast, context-efficient repository tools for AI agents.
6
+
7
+ FastCtx is a local Rust tool runtime. It provides file reading, content search, file discovery, batch replacement, and Bash command execution through MCP.
8
+
9
+ Repository operations run in a persistent process with stable input schemas and output formats. The model can gather the context it needs in fewer steps and spend more attention on understanding code, planning changes, and verifying results.
10
+
11
+ Each `fastctx serve` process is a thin stdio proxy. Proxies for the same user and FastCtx build share one private local control center, including its search executor and global admission limits, while every MCP connection keeps its own working directory, native environment, cancellation state, and background-output cursor.
12
+
13
+ An MCP session ends when its host ends it, never because the shared runtime had a problem. If the control center becomes unreachable, the proxy answers the calls it can no longer complete with an explicit error, reconnects to a replacement — starting one, or running the engine inside the proxy itself — and carries on over the same stdio transport. Side-effecting calls are never replayed. The control center itself stays resident while any host process that used it is still running, and exits ten minutes after the last of them is gone, with no connection, no active request, and no running background job.
14
+
15
+ ```console
16
+ npm install --global fastctx
17
+ fastctx
18
+ ```
19
+
20
+ The `fastctx` command opens the control terminal. Review the proposed changes, select **Connect to Codex**, then start a new ChatGPT / Codex session.
21
+
22
+ FastCtx currently provides first-class setup for ChatGPT App and Codex CLI. Any MCP client can also register `fastctx serve` directly.
23
+
24
+ ## What FastCtx solves
25
+
26
+ Coding agents often assemble shell commands on the fly when they access a repository. They have to handle quotes, escaping, paths, and platform differences, then extract the useful information from terminal output. A simple file read or symbol search can take several tool calls just to confirm that the command is correct and the result is complete.
27
+
28
+ This work consumes context and reasoning. The model tracks the code problem and the tool mechanics at the same time: whether the PowerShell syntax is correct, whether a path was escaped correctly, whether the encoding produced mojibake, and whether the host truncated a long result. More tool overhead leaves less room for the repository itself.
29
+
30
+ FastCtx turns common repository operations into structured input and output. The model provides parameters such as a path, pattern, range, and mode. The Rust runtime handles command construction, directory traversal, encoding, pagination, and output boundaries.
31
+
32
+ The tools cover the main parts of a coding task:
33
+
34
+ - `inspect_local_file` reads text, images, PDFs, and raw bytes;
35
+ - `grep` searches file contents;
36
+ - `glob` finds files;
37
+ - `replace` performs mechanical batch replacement;
38
+ - `run`, `run_background`, `job_output`, `job_kill`, and `job_list` execute Bash commands and manage persistent long-running jobs.
39
+
40
+ This greatly reduces the attention the model spends on tool mechanics, such as checking whether a PowerShell command is correct. It improves context efficiency and helps tasks finish faster with better results.
41
+
42
+ ## Installation
43
+
44
+ ### Install with npm
45
+
46
+ Requires Node.js 18 or later:
47
+
48
+ ```console
49
+ npm install --global fastctx
50
+ fastctx
51
+ ```
52
+
53
+ The first launch opens the full-screen control terminal. The interface supports 17 languages and provides these main actions:
54
+
55
+ 1. Adjust the output tier and provider-aware output protection;
56
+ 2. Keep grep/glob on automatic CPU parallelism or set an explicit core limit;
57
+ 3. Enable **Bash terminal** when needed;
58
+ 4. Set current-user background-job storage, concurrency, and AI list page limits;
59
+ 5. Inspect every currently running job across FastCtx sessions, follow its output, and stop it on the **Jobs** screen;
60
+ 6. Reset all user preferences to factory defaults through a confirmation screen;
61
+ 7. Review every host configuration change on the Connect to Codex screen, confirm it, and restart the ChatGPT / Codex session.
62
+
63
+ Connecting copies the current binary to `~/.fastctx/bin/` and points the host configuration at that stable path. The connected setup keeps working after npm cache cleanup or upgrades.
64
+
65
+ On launch, FastCtx checks its launch channel for updates before the main menu opens. A brief checking screen appears and the wait is strictly bounded: if the check cannot finish — offline, timeout, rate limiting — FastCtx enters silently, and the dedicated **Update** screen still offers a manual check at any time. When a newer version is installable, the update screen opens directly and asks whether to **Update & restart** or **Continue** into the current version. Successful results are cached for 24 hours in machine-private storage outside `~/.fastctx`, so most launches skip the network entirely. npm launches query the exact launcher package through a fresh isolated cache with `--prefer-online`; direct GitHub Release executables read the stable tag from GitHub's `releases/latest` web redirect.
66
+
67
+ If GitHub has published a release but npm has not exposed the matching version yet, FastCtx shows a propagation screen instead of trusting stale metadata. **Retry** always uses another isolated cache; it never clears or mutates the user's normal npm cache. Transient network or rate-limit failures stay quiet and are recorded under **Status**; malformed publication metadata produces one warning. Status also offers a manual check that bypasses the 24-hour TTL. An accepted npm update installs the exact version with lifecycle scripts disabled. A GitHub Release update downloads this repository's platform archive and aggregate `SHA256SUMS`, verifies the archive before safely extracting the binary, probes the downloaded version, replaces the executable atomically, and rolls back when restart health fails. A failed npm update restores the exact previous package version; every failed update reopens the previous TUI with a warning. After a successful restart, the owned `~/.fastctx/bin/` copy is synchronized; externally changed copies are left untouched. Restart Codex after an update so existing sessions and their build-isolated control center are replaced by the new build.
68
+
69
+ `cargo install` builds and the internal `~/.fastctx/bin/` runtime are not self-updated. Set `FASTCTX_DISABLE_UPDATE_CHECK=1` to disable the TUI startup check.
70
+
71
+ **Removal** stops FastCtx process images running from the managed bin directory, removes the configuration managed by FastCtx, and deletes its managed data. Shared settings changed by the user after connecting are preserved.
72
+
73
+ ### If the install returns 404
74
+
75
+ Mirror registries copy new releases from the official registry on a delay. Right after a release, an install through a mirror can fail with `404 Not Found` — most often on the platform package, which npm installs as an optional dependency and skips silently, leaving `fastctx` installed but unable to start.
76
+
77
+ Install once from the official registry:
78
+
79
+ ```console
80
+ npm install --global fastctx --registry=https://registry.npmjs.org/
81
+ ```
82
+
83
+ The flag applies to this command only and leaves the npm configuration unchanged. To use the official registry permanently:
84
+
85
+ ```console
86
+ npm config set registry https://registry.npmjs.org/ --location=user
87
+ ```
88
+
89
+ After installation, the **Update** screen probes the npm registry configured on this machine, the official registry, and registry.npmmirror.com, then installs from the first source that carries both the launcher and the matching platform package. Version numbers always come from the official registry and GitHub, so a mirror can never announce a version the official source has not published.
90
+
91
+ ### One-off run
92
+
93
+ ```console
94
+ npx fastctx
95
+ ```
96
+
97
+ `npx` opens the same control terminal without a global installation. Connecting still copies the binary to `~/.fastctx/bin/`, so the connected setup keeps working after the npx cache is cleaned; only the `fastctx` command itself requires the global installation.
98
+
99
+ ### Non-interactive use
100
+
101
+ ```console
102
+ fastctx apply --tier standard --yes
103
+ fastctx status
104
+ fastctx jobs
105
+ fastctx jobs kill j-a1b2c3
106
+ fastctx unapply --yes
107
+ ```
108
+
109
+ - `apply`: install FastCtx and write the configuration;
110
+ - `status`: check the configuration, binary, and MCP handshake;
111
+ - `jobs`: list running background jobs;
112
+ - `jobs kill <job_id>`: stop one background job and its full process tree;
113
+ - `unapply`: remove the content managed by FastCtx;
114
+ - `lang <code>`: set the control terminal language.
115
+
116
+ `status` uses three states: `[PASS]`, `[INFO]`, and `[FAIL]`. It also reports the detected search CPU ceiling and the configured/effective parallelism. A `[FAIL]` result returns a non-zero exit code.
117
+
118
+ ### Tool limits and settings reset
119
+
120
+ grep/glob uses automatic parallelism by default: the operating system's available parallelism, capped at 16. In **Config → Search**, choose a preset with ←/→ or press Enter and type `auto` or any integer in the displayed `1..=maximum` range. The setting is loaded when the shared control center starts and takes effect after that control center restarts, which happens once every Codex process using it has exited. Reconnecting is not required.
121
+
122
+ The same setting can be written manually in `~/.fastctx/config.toml`:
123
+
124
+ ```toml
125
+ [search]
126
+ max_cpu_cores = 4
127
+ ```
128
+
129
+ Omitting the key keeps the previous automatic behavior. Invalid types, empty values, zero, negative numbers, and values above the engine's displayed ceiling prevent a session from starting and produce a diagnostic without rewriting the file. The limit sets one request's effective search parallelism to its base lane plus shared extra workers, at most N. Across every session in the per-user control center, concurrent requests retain independent base lanes but share one pool of at most N−1 extra lanes, so the upper bound for R concurrent requests is R+N−1. This is not CPU affinity or a strict system-wide governor.
130
+
131
+ replace accepts files and replacement results up to 256 MiB by default. In **Config → Editing**, choose a coarse 64 MiB–4 GiB preset with ←/→. Saving takes effect on the next replace request, including requests from an already-open Codex session, and does not require reconnecting. Larger limits allow replace to use more memory; values set too high may cause an out-of-memory failure.
132
+
133
+ The same limit can be written manually; 64 MiB is the minimum and 4096 MiB is the maximum:
134
+
135
+ ```toml
136
+ [replace]
137
+ max_file_size_mib = 512
138
+ ```
139
+
140
+ **Config → Reset → Reset all settings** opens with **No** selected. Confirming restores every user preference, including language, output budgets, Bash/job limits, search CPU limit, replace file limit, and update settings. It preserves the connection receipt, installed binary, host configuration, and running jobs. Restoring the default 1024 MiB job-history quota may immediately evict the oldest finished records above that quota.
141
+
142
+ ### Other distribution channels
143
+
144
+ ```console
145
+ cargo install fastctx --locked
146
+ ```
147
+
148
+ GitHub Releases provides zip archives for Windows x64 and Windows arm64, and executable-preserving tar.gz archives for Linux x64, macOS x64, and macOS arm64. Every archive includes the binary and license notices; verify it with the release's aggregate `SHA256SUMS`.
149
+
150
+ ## Tools
151
+
152
+ FastCtx provides nine MCP tools:
153
+
154
+ | Tool | Purpose |
155
+ |---|---|
156
+ | `inspect_local_file` | Read one file in any supported format, or batch 1–32 text files |
157
+ | `grep` | Search contents in a file or repository tree |
158
+ | `glob` | Find files by path pattern |
159
+ | `replace` | Apply mechanical batch replacements to files or a repository tree |
160
+ | `run` | Run a Bash command in the foreground |
161
+ | `run_background` | Start a background Bash job |
162
+ | `job_output` | Query a background job and show its newest unseen output |
163
+ | `job_kill` | Stop the full process tree of a background job |
164
+ | `job_list` | Rediscover running and retained finished jobs |
165
+
166
+ `inspect_local_file`, `grep`, `glob`, and `replace` are published by default. The other five tools are enabled with the **Bash terminal** setting in the control terminal. Once enabled, they share the `mcp__fastctx` namespace with the file tools; how a host spells an individual tool inside that namespace is the host's own convention.
167
+
168
+ ### `inspect_local_file`
169
+
170
+ `inspect_local_file` returns 1-based line numbers for text and supports paging:
171
+
172
+ ```json
173
+ {
174
+ "file_path": "V:/repo/src/main.rs",
175
+ "offset": 120,
176
+ "limit": 40
177
+ }
178
+ ```
179
+
180
+ ```text
181
+ 120 fn main() {
182
+ 121 ...
183
+ 159 }
184
+
185
+ (Partial: lines 120-159 of 512 shown. Continue with offset=160.)
186
+ ```
187
+
188
+ The continuation parameters in the final status line can be used directly in the next call. In this example, pass `offset=160` to read the next section.
189
+
190
+ When several known text files are relevant, batch them into one call instead of paying one agent round trip per file:
191
+
192
+ ```json
193
+ {
194
+ "files": [
195
+ {"path": "V:/repo/src/main.rs", "offset": 120, "limit": 40},
196
+ {"path": "V:/repo/src/config.rs"},
197
+ {"path": "V:/repo/docs/legacy.txt", "encoding": "gbk"}
198
+ ],
199
+ "limit": 400
200
+ }
201
+ ```
202
+
203
+ The `files` form accepts 1–32 text files, preserves request order, and packs them into one shared read budget. A top-level `limit` applies to every entry that omits its own; the first entry above overrides the default. A missing, empty, binary, or undecodable member is reported inside its own segment while the remaining files continue. If the budget fills, the final `Partial` line contains the exact compact `files=[...]` array for the next call, including per-file offsets, remaining limits, and encodings. Images, PDFs, and hex view remain single-file calls.
204
+
205
+ `inspect_local_file` also supports:
206
+
207
+ - PNG, JPG, GIF, WebP, and BMP images;
208
+ - PDF text layers and rendered page images;
209
+ - a paged hex view for any file;
210
+ - UTF-8, BOM-based encodings, and common legacy encodings.
211
+
212
+ Automatic encoding detection accepts results with sufficient evidence. When the encoding is ambiguous, the error lists candidates and retry options. Pass `encoding` to select one explicitly:
213
+
214
+ ```json
215
+ {
216
+ "file_path": "V:/repo/docs/legacy.txt",
217
+ "encoding": "gbk"
218
+ }
219
+ ```
220
+
221
+ Use the hex view for binary files:
222
+
223
+ ```json
224
+ {
225
+ "file_path": "V:/repo/data/cache.bin",
226
+ "view": "hex"
227
+ }
228
+ ```
229
+
230
+ ### `grep`
231
+
232
+ `grep` uses the Rust regex engine from the ripgrep family:
233
+
234
+ ```json
235
+ {
236
+ "pattern": "fn \\w+_lock",
237
+ "path": "V:/repo/src",
238
+ "output_mode": "content",
239
+ "context": 1
240
+ }
241
+ ```
242
+
243
+ ```text
244
+ V:/repo/src/edit/locks.rs
245
+ 62-/// Cross-process lock keyed by file identity.
246
+ 63:pub fn acquire_path_lock(identity: &PathIdentity) -> LockGuard {
247
+ 64- ...
248
+
249
+ (Complete: all 1 result shown.)
250
+ ```
251
+
252
+ `output_mode` has four values:
253
+
254
+ - `files_with_matches`: return matching files;
255
+ - `content`: show matches grouped by file;
256
+ - `count`: return the occurrence count for each file;
257
+ - `summary`: scan the full target and return global totals.
258
+
259
+ `grep` respects `.gitignore` and `.ignore` by default, includes hidden files, and excludes `.git` and binary files. Common filters include `glob`, `type`, `case_insensitive`, `multiline`, and `context`. Page through results with `head_limit` and `offset`.
260
+
261
+ Files with uncertain encodings appear in a skip report with their path, reason, and resolution parameters. Use `encoding` for a single file and `fallback_encoding` for a directory search.
262
+
263
+ If a file changes during a directory search, `grep` reports that file as skipped and continues; a changing single-file target returns an error so partial matches never masquerade as complete results.
264
+
265
+ A directory the walk cannot enter — denied permissions, a locked file, a symlink loop — never discards the results found around it. `grep`, `glob`, and `replace` return what they reached, list each unreachable path with its cause, and count them in the terminal note. An unreadable search root is still an error, because a walk that reached nothing cannot report that it found nothing.
266
+
267
+ ### `glob`
268
+
269
+ `glob` finds files with a pattern relative to the search root:
270
+
271
+ ```json
272
+ {
273
+ "pattern": "**/*.toml",
274
+ "path": "V:/repo",
275
+ "sort": "modified",
276
+ "output_mode": "details"
277
+ }
278
+ ```
279
+
280
+ ```text
281
+ {"path":"V:/repo/crates/core/Cargo.toml","bytes":1842,"modified":"2026-08-23T16:42:18.123456700Z"}
282
+ {"path":"V:/repo/Cargo.toml","bytes":2937,"modified":"2026-08-23T15:07:03.000000000Z"}
283
+
284
+ (Complete: all 2 files shown.)
285
+ ```
286
+
287
+ Main parameters:
288
+
289
+ - `filter_mode: "ignore"` (default): respect plain `.ignore` files only;
290
+ - `filter_mode: "all"`: disable plain `.ignore` filtering;
291
+ - `output_mode: "paths"` (default): return one absolute path per line;
292
+ - `output_mode: "details"`: return one compact JSON object per line with path, byte size, and a fixed nine-digit RFC 3339 UTC modification time;
293
+ - `sort: "path"`: use a stable path order;
294
+ - `sort: "modified"`: order files from newest to oldest;
295
+ - `offset` / `limit`: page through the result set.
296
+
297
+ `glob` never reads `.gitignore`, `.git/info/exclude`, or the user's global Git ignore, and it never hides `.git` automatically. Hidden and Git-internal files remain ordinary candidates; exclude unwanted trees explicitly with a negative pattern such as `!target/**` or `!.git/**`. The legacy value `filter_mode: "project"` is still accepted and behaves as `"ignore"`, but is no longer published in the tool schema. `grep` and `replace` keep their existing Git-ignore behavior.
298
+
299
+ `grep` and `glob` render filename components that are unsafe to place directly in a line as reversible `~fastctx~b...~` or `~fastctx~w...~` escapes. Copy the whole component exactly into a later grep/glob call; do not decode or edit it.
300
+
301
+ ### `replace`
302
+
303
+ `replace` handles mechanical, deterministic batch changes such as symbol renames, import rewrites, configuration key migrations, and fixed-pattern deletion. Generated code changes and per-location semantic edits are handled by the host's `apply_patch` tool.
304
+
305
+ ```json
306
+ {
307
+ "pattern": "old_name\\(",
308
+ "replacement": "new_name(",
309
+ "path": "V:/repo/src",
310
+ "glob": ["**/*.rs"],
311
+ "dry_run": true
312
+ }
313
+ ```
314
+
315
+ ```text
316
+ ...
317
+
318
+ (Complete: dry run — 12 matches in 3 files; nothing written.)
319
+ ```
320
+
321
+ `replace` freezes the candidate set and counts every match before the first write. Use `dry_run` for preview and `max_replacements` to cap the change scope.
322
+
323
+ Each file is checked again before commit. Writes use atomic replacement in the same directory and preserve the original encoding, BOM, line endings, trailing newline, Unix mode, and untouched bytes. Concurrent changes move the affected file into the failure report while the remaining files continue.
324
+
325
+ ### `run`
326
+
327
+ `run` executes a Bash command in the foreground and returns merged stdout, stderr, and the exit code. It uses Git Bash on Windows and the system Bash on macOS and Linux.
328
+
329
+ ```json
330
+ {
331
+ "command": "cargo test --quiet 2>&1 | tail -n 40",
332
+ "timeout_ms": 180000
333
+ }
334
+ ```
335
+
336
+ Commands run in a non-interactive environment. Installation, confirmation, and editor commands need flags such as `-y` and `--no-edit`. Non-zero exit codes are returned as execution results.
337
+
338
+ On Windows, every FastCtx-owned non-interactive child process is created without allocating a console window, including Bash discovery, foreground/background Bash, detached supervisors, and doctor probes. There is no hidden-window parameter to remember. A command that explicitly launches a GUI or a new terminal still has that visible effect.
339
+
340
+ Output uses bounded memory. When output exceeds the response capacity, the final status line reports the truncated range and gives a path to the complete result: redirect the command output to a file, then page through it with `inspect_local_file`.
341
+
342
+ #### Command environment
343
+
344
+ A stdio MCP server does not receive the environment its user configured. The host clears the child environment and re-adds only a fixed core list of names, so variables such as `JAVA_HOME`, `GOPATH`, or `CUDA_PATH` never reach FastCtx and would otherwise never reach the commands it runs.
345
+
346
+ On Windows, FastCtx restores the environment the operating system persists for the user — the system and user entries of the Windows **Environment Variables** dialog — and lays whatever the host did provide on top of it, so host values always win. `PATH` is the single exception and is a union: the search path that arrived stays exactly as it is, and only persisted directories it does not already contain are appended after it. On macOS and Linux the login shell already sources the profile where a user's environment lives, so nothing is reconstructed.
347
+
348
+ `run` and `run_background` use a login shell (`bash -lc`) by default so profile-managed toolchains such as nvm, pyenv, and rustup resolve; pass `login_shell: false` for a clean `--noprofile --norc` shell. On Windows a login shell is given the complete Windows search path unless `MSYS2_PATH_TYPE` is already set, in which case that choice is respected.
349
+
350
+ Two environment variables configure this. Both are read from either the persisted environment or the `env` table of the FastCtx entry in the host's MCP server configuration:
351
+
352
+ | Variable | Effect |
353
+ | --- | --- |
354
+ | `FASTCTX_INHERIT_ENVIRONMENT=0` | Skip the restore, leaving commands with the environment the host provided. |
355
+ | `FASTCTX_BASH` | Absolute path to the Bash to use. FastCtx requires GNU Bash and never accepts the `System32\bash.exe` WSL launcher. |
356
+
357
+ ### `run_background`
358
+
359
+ `run_background` starts a background Bash job and returns a job id immediately. It is useful for builds, tests, development servers, and other long-running commands.
360
+
361
+ Each job is owned by a detached supervisor rather than by the MCP server. It keeps running across server exits, ChatGPT / Codex restarts, and session changes until the command exits or `job_kill` stops it. There is no background timeout parameter.
362
+
363
+ Output and exit status are stored under `~/.fastctx/jobs/`, so another FastCtx session can resume the same job by id. For jobs started by the current format, output is appended to a plain log file whose path is returned when the job starts, so `inspect_local_file` and `grep` work on the retained prefix directly. At supervisor startup, each job freezes a hard ceiling for the combined log and line index from the current `fastshell.job_storage_limit_mib` setting. If output reaches that ceiling, FastCtx keeps draining the child process so the command can finish, stops persisting further bytes, and records an explicit truncation notice without changing the command's exit code.
364
+
365
+ While one MCP session has jobs that it started or queried, every successful text result from that session carries a one-line background readout with each job's current state and elapsed time. The readout refreshes only when another tool is called; it is not a notification and nothing is pushed while the caller is idle. A finished entry remains visible until that session handles it with `job_output` or `job_kill`.
366
+
367
+ ### `job_output`
368
+
369
+ `job_output` queries a background job, including jobs started in earlier sessions, and reports `running`, `exited`, or `interrupted` together with the newest output the caller has not been shown. `wait_ms` (0–240000, default 30000) is how long the query may take: it returns as soon as the job ends and otherwise waits the window out; intermediate lines do not end the wait. Pass `wait_ms=0` for an immediate snapshot, and raise it only when there is nothing else to do because the call blocks. Long current-format output is windowed — the newest lines that fit, plus the start of the log on the first call — and a note names the exact lines that were skipped and the log path to read them from. Line numbers in that log are the same `seq` numbers `after_seq` takes, so moving between the two tools needs no translation. Records written by the preceding segmented format remain readable, including while an older supervisor is still appending, but they do not advertise direct log coordinates and cannot recover bytes that their original rolling window already evicted.
370
+
371
+ `Complete` appears only after the job ends; a development server or watcher may never reach it. Before the per-job disk ceiling is reached, anything a response leaves out is still one `inspect_local_file` or `grep` away. After the ceiling is reached, `job_output` and the Jobs dashboard identify the last retained sequence and explain that the supervisor continued draining without persistence. The compatibility limitation above applies only to records created by the preceding format.
372
+
373
+ ### `job_kill`
374
+
375
+ `job_kill` stops the selected background job and its full process tree. If the job has already exited, the call returns the existing exit status.
376
+
377
+ ### `job_list`
378
+
379
+ `job_list` defaults to `status="running"`. Use `status="finished"` to inspect retained exited or interrupted records, and `status="all"` only when both lifecycles are needed. Results are newest first within each lifecycle. `offset` continues a page; `limit` overrides the saved page size for one call.
380
+
381
+ Finished records have no time-to-live. FastCtx retains them until the current user's `fastshell.job_storage_limit_mib` limit requires eviction of the oldest finished records. The default is 1024 MiB. Running jobs and their records are never evicted; `fastshell.max_running_jobs` limits concurrent jobs across all FastCtx sessions for that user and defaults to 128. `fastshell.job_list_limit` is the default page size (20, valid range 1–100). All three settings take effect immediately when saved and do not require reconnecting; the TUI presets for page size are 10 / 20 / 50 / 100.
382
+
383
+ The TUI **Jobs** dashboard scans this same current-user registry but shows only jobs that are currently running, aggregated from every FastCtx session and TUI instance. A finished job disappears with a short notice that its retained output remains available to the agent through `job_output`. Jobs are grouped by a source tag with workspace and runtime-process context. Fixed list columns keep relative age and job ids aligned, while long ASCII or CJK commands end with an ellipsis at one shared edge. The detail panel shows the exact UTC start time to the second and a live `HH:MM:SS` elapsed time. Horizontal and vertical output navigation remains available; one width-aware footer row keeps the essential keys visible and adds `←/→ output`, `PgUp/PgDn scroll`, and `F follow` when space permits. ChatGPT / Codex does not expose conversation titles or ids to the MCP server, so FastCtx does not invent one.
384
+
385
+ ## Security and privacy
386
+
387
+ The FastCtx MCP server inherits the local permissions of the host process.
388
+
389
+ | Capability | Default state | Access scope |
390
+ |---|---|---|
391
+ | `inspect_local_file` / `grep` / `glob` | Enabled | Local files readable by the host process |
392
+ | `replace` | Enabled | Local file writes with dry-run, CAS, and atomic replacement safeguards |
393
+ | Bash tools | Disabled | Bash command execution after the user enables them |
394
+ | TUI update check | Enabled for npm and GitHub Release launches | Version metadata from `registry.npmjs.org` and GitHub's `releases/latest` web redirect; downloads require explicit confirmation |
395
+ | MCP runtime network requests | None | `serve`, private local proxy traffic, and tool calls perform no telemetry or update traffic |
396
+
397
+ The startup check sends the FastCtx version, normal HTTPS request metadata, and npm's standard registry request; it never sends repository paths, job data, or file contents. Background jobs persist their command, working directory, retained output prefix, truncation state, and exit status only in the current user's private `~/.fastctx/jobs/` directory. Proxy-to-control-center traffic stays on an owner-private Unix-domain socket or Windows named pipe. FastCtx does not upload this data. Bash commands can access the network according to the command itself. Prebuilt binaries include the PDF engine.
398
+
399
+ The MCP server runs outside the host filesystem sandbox. Use an approval mode when every write and command execution should be reviewed:
400
+
401
+ ```toml
402
+ [mcp_servers.fastctx]
403
+ default_tools_approval_mode = "writes"
404
+ ```
405
+
406
+ - `writes`: review `replace` and shell execution tools;
407
+ - `prompt`: review every tool call.
408
+
409
+ `replace` is published with the default file tools. The host's read-only mode covers the host's own tools. MCP writes still run with the server process permissions. Set `writes` or `prompt` when the workflow depends on a read-only boundary.
410
+
411
+ ## What FastCtx changes
412
+
413
+ FastCtx uses or manages these paths and settings:
414
+
415
+ - `~/.fastctx/bin/fastctx(.exe)`: the stable self-installed binary;
416
+ - `~/.fastctx/config.toml`: control terminal settings and the connection receipt;
417
+ - `~/.fastctx/jobs/`: persistent background-job records and current-format full output logs, created on demand by `run_background`;
418
+ - `[mcp_servers.fastctx]` in `~/.codex/config.toml`, including `tool_timeout_sec = 300`;
419
+ - the `mcp__fastctx` entry in `direct_only_tool_namespaces`;
420
+ - the marker-delimited FastCtx block in `~/.codex/AGENTS.md`;
421
+ - the selected `tool_output_token_limit` value after user confirmation.
422
+
423
+ FastCtx edits existing TOML with `toml_edit`, preserving comments, formatting, and unrelated configuration. Removal removes entries according to write ownership and preserves later user changes. It stops running background jobs before removing `~/.fastctx/`.
424
+
425
+ ## License
426
+
427
+ FastCtx is licensed under the Apache License 2.0.
428
+
429
+ If you redistribute FastCtx, bundle it into another product, or build on top of it, Section 4(d) requires you to reproduce the attribution notice in [`NOTICE`](./NOTICE) wherever third-party notices normally appear — for a source repository, that means your README. That notice credits https://github.com/yc-duan/fastctx and states that your changes are your own work and your sole responsibility, carrying no endorsement or liability from this project's author. Section 4(b) separately requires files you modified to carry prominent notices that you changed them.
430
+
431
+ Third-party notices for the bundled Pdfium build are listed in [`THIRD_PARTY_LICENSES.md`](./THIRD_PARTY_LICENSES.md).
432
+
433
+ ## Contact
434
+
435
+ FastCtx is created and maintained by [yc-duan](https://github.com/yc-duan). For integration, redistribution, partnership, or anything else, feel free to reach out: dy2958830371@gmail.com.
436
+
437
+ ## Acknowledgements
438
+
439
+ Thanks to the [linuxdo](https://linux.do/) community for discussion, sharing, and feedback.
@@ -0,0 +1,17 @@
1
+ # Third-party licenses
2
+
3
+ The `fastctx` executable embeds the dynamic Pdfium library from
4
+ `bblanchon/pdfium-binaries` release `chromium/7763`. The archive and extracted
5
+ library are both verified against pinned SHA-256 digests during the build.
6
+
7
+ The complete notices shipped by that release are preserved under
8
+ `third-party/pdfium-7763/`, including the Pdfium BSD license and notices for
9
+ Abseil, AGG, fast_float, FreeType, ICU, Little CMS, libjpeg-turbo, OpenJPEG,
10
+ libpng, libtiff, LLVM libc, simdutf, and zlib.
11
+
12
+ Every Rust crate linked into the executable is listed in
13
+ [`THIRD_PARTY_LICENSES_RUST.md`](./THIRD_PARTY_LICENSES_RUST.md) together with the
14
+ full text of each license that applies. That inventory is generated from
15
+ `Cargo.lock` and re-checked against it on every CI run.
16
+
17
+ The project itself is available under the Apache License 2.0.