@skylence-ai/skyline 1.0.31

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 (3) hide show
  1. package/README.md +238 -0
  2. package/bin.js +48 -0
  3. package/package.json +34 -0
package/README.md ADDED
@@ -0,0 +1,238 @@
1
+ # skyline
2
+
3
+ [![CI](https://github.com/skylence-be/binary-skyline/actions/workflows/ci.yml/badge.svg)](https://github.com/skylence-be/binary-skyline/actions/workflows/ci.yml)
4
+ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](https://github.com/skylence-be/binary-skyline/blob/main/LICENSE)
5
+
6
+ A search-and-edit toolkit that lets AI coding assistants change your code safely. Every edit
7
+ is bound to a content fingerprint and refused if the file changed since it was read, so an
8
+ assistant never silently overwrites your work. Search and refactoring understand code
9
+ structure, not just text.
10
+
11
+ ## Install
12
+
13
+ The recommended setup is a small always-on background service (a daemon) that your AI client
14
+ talks to. Start it once and every tool call is fast.
15
+
16
+ <details>
17
+ <summary>Why a daemon instead of a per-call binary?</summary>
18
+
19
+ - No cold starts: the warm daemon answers a full `tools/list` round-trip in
20
+ **10 to 40 ms**. A per-session stdio server pays its full startup cost
21
+ before the first call, every session.
22
+ - Language servers stay warm: the one-time cold index on a ~224k-line workspace
23
+ took **95 s**; warm calls are **sub-second**. With a daemon that price is paid
24
+ once per workspace, not once per session.
25
+ - One process for every client: Claude Code, other MCP clients, and scripts all
26
+ share the same warm state, one audit stream, and one bench stream.
27
+ - The per-session stdio mode works too; it just re-pays startup and indexing in
28
+ every new session. Numbers: [docs/benchmarks.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/benchmarks.md). Setup for
29
+ both modes: [docs/install.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/install.md).
30
+
31
+ </details>
32
+
33
+ ### 1. Install (npm — prebuilt binary, every platform)
34
+
35
+ ```bash
36
+ npm install -g @skylence-ai/skyline
37
+ ```
38
+
39
+ Puts the `skyline` binary on your PATH (macOS arm64/x64, Linux arm64/x64,
40
+ Windows x64/arm64) via the matching `@skylence-ai/skyline-<platform>` optional
41
+ dependency — no native installer or compile step. Alternatives:
42
+ `cargo binstall skyline`, or a prebuilt archive from
43
+ [GitHub Releases](https://github.com/skylence-be/binary-skyline/releases).
44
+
45
+ ### 2. Start the shared background service (pick any free port)
46
+ ```bash
47
+ skyline daemon start --port 7333
48
+ ```
49
+
50
+ To survive reboots, register it as an OS service instead: `skyline daemon install --port 7333` (see [docs/install.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/install.md) for details).
51
+
52
+ ### 3. Tell your AI client (here, Claude Code) about it
53
+ ```bash
54
+ claude mcp add --scope user --transport http skyline http://127.0.0.1:7333/mcp
55
+ ```
56
+
57
+ Check it is up with `skyline daemon status` (the port should read `running`). That is it.
58
+
59
+ Other install methods are in [docs/install.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/install.md).
60
+
61
+ ### 4. Prompts for your agent
62
+
63
+ Paste this into your agent's instructions so it picks the right tool:
64
+
65
+ ```text
66
+ Prefer skyline's MCP tools over your built-in file read, edit, and search tools for all code work, and especially when a skyline HTTP MCP server is registered (a shared, always-warm daemon, so calls stay cheap). If skyline becomes unavailable mid-session (tools dropped from your tool list, connection refused or closed), do NOT silently fall back to your built-in tools: retry once, then pause code work, report the outage to your orchestrator or user, and wait for skyline to be restored before continuing. Use `skyline_tree` to get project shape and orient in an unfamiliar repo (every output line is a plain path you pass straight to `skyline_read`), `skyline_read` to read a file (it returns a `¶path#TAG` anchor; never reconstruct that header by hand, copy it back verbatim), `skyline_grep` for regex/text search, `skyline_sgrep` for structural/AST search, `skyline_edit` to apply hash-guarded line edits using that anchor, `skyline_srewrite` for one-pass structural find-and-replace across a file or directory, and `skyline_format` to run the language formatter (rustfmt, gofmt, prettier) through the audited pipeline; use `skyline_git` for repo status and compressed unstaged diffs (context stripped, each file section headed by a real `¶path#TAG` anchor so you can edit straight from the diff output), and `skyline_test` to run the test suite (failures come back with `¶path#TAG` anchors for direct editing; `exit_code` is authoritative — a nonzero exit with no parsed failures means a build error, consult the raw output path); use `skyline_run` with an argv ARRAY (never a shell string; there is no shell) for any simple command such as git, cargo, docker, gh, or npm (output comes back compressed with the full raw output teed to a temp file and the invocation audited; to run several commands in one round-trip pass `argv_list`, an array of argv arrays, optionally with `parallel: true`, and supply exactly one of `argv` or `argv_list`), falling back to your built-in Bash tool only for compound shell features (pipes, &&, redirection, command substitution); use `skyline_json` to query or reshape JSON without paying tokens for or leaking the values, instead of piping a file through Bash and jq; when the task is about a SYMBOL rather than text, use the semantic tools: `skyline_definition` (where is it defined, starting from a call site), `skyline_references` (every true caller; comments and strings never match), `skyline_rename` (whole-workspace rename, preview with dry_run), `skyline_symbols` (find by name fragment), and `skyline_diagnostics` (does the file still typecheck after an edit; per-file, so use the build tool for whole-project checks); always read (or grep/sgrep) to get a fresh anchor before editing, pass it back unchanged, and if an edit is rejected as stale, re-read to refresh the tag and retry. For observability (off by default): `skyline_observability_status` to see what is enabled, `skyline_observability_set` to toggle the audit/devlog/bench streams, `skyline_audit_tail` and `skyline_log_tail` to read the mutation-audit and diagnostic logs, `skyline_bench_report` for timing aggregates, and `skyline_audit_prune` / `skyline_devlog_prune` / `skyline_bench_prune` to trim them.
67
+ ```
68
+
69
+ Or skip the manual setup entirely and hand your agent this:
70
+
71
+ ```text
72
+ Set up skyline for me: install it with `npm install -g @skylence-ai/skyline` (prebuilt binaries for every platform, incl Windows arm64), install the shared HTTP MCP daemon as a supervised autostart service with `skyline daemon install --port 7333` (so it survives sleep cycles and restarts itself if it dies; plain `skyline daemon start` runs unsupervised and dies with its parent), register it for all my projects with `claude mcp add --scope user --transport http skyline http://127.0.0.1:7333/mcp`, then verify: `skyline daemon status` must show the port as `running`, and `claude mcp list` must show skyline as connected. Do NOT probe the endpoint with raw curl: it is a stateful streamable-HTTP MCP server that requires an initialize handshake, an Accept header for both application/json and text/event-stream, and a session id, so ad-hoc curl calls fail by design; `claude mcp list` is the correct connectivity check, and the tools (e.g. `skyline_version`) become callable in your next session. If the port is taken, pick a free one and redo both the install and add commands with it.
73
+ ```
74
+
75
+ ## The numbers
76
+
77
+ The search result IS the edit handle, so edit cost stays flat (~60 tokens whether the
78
+ file is 300 lines or 10,000). Four blind evaluation rounds, measured with skyline's
79
+ own bench stream:
80
+
81
+ - Every mid-edit race became a one-line rejection, never a silent overwrite. Two
82
+ agents editing the same file simultaneously, blind to each other: zero lost
83
+ updates ([docs/concurrency.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/concurrency.md)).
84
+ - Repo-scale questions answered in one line instead of a match dump.
85
+ - A 404-file rewrite converged in one extra call; the residual report said exactly
86
+ what remained and why.
87
+ - Under drift, conflicts, and out-of-band edits, a blind agent re-grounded before
88
+ editing and reconstructed the change history from the audit stream.
89
+
90
+ | | Built-in read→edit | skyline |
91
+ |---|---|---|
92
+ | One edit in a 10,000-line file | ~83,500 tokens | **~62 tokens** (1,336× less) |
93
+ | Repo-wide structural count (896 Go files) | full match dump, no exact total | **1 line**: `282 matches in 105 files.` |
94
+ | 213-file structural rewrite | no built-in equivalent | **3 calls, ~8.3k tokens**, previewed + hash-guarded |
95
+
96
+ Measured, not modeled: methodology and full tables in [docs/benchmarks.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/benchmarks.md).
97
+
98
+ ## What problem does this solve?
99
+
100
+ - **Silent overwrites.** If a file changed after the assistant read it (you saved, a
101
+ formatter ran), text-matching edits quietly destroy work. skyline fingerprints every
102
+ read and refuses stale edits.
103
+ - **Text-blind search.** Find-and-replace renames hit comments and strings. skyline
104
+ rewrites by structure: real calls change, comments stay.
105
+ - **Token bloat.** Read-then-edit costs grow with file size; search returns dumps.
106
+ skyline replies stay small: ~60-token edits, one-line counts, per-file rewrite
107
+ summaries. Up to 48% less traffic on combined tasks; one blind run took 14
108
+ round-trips where built-ins needed ~450.
109
+ - **Cold starts.** The daemon keeps one warm process (and warm language servers) for
110
+ every client.
111
+
112
+ ## Why it is better
113
+
114
+ These come from running skyline against real repositories and measuring with its own tools.
115
+ Full detail and the methodology are in [docs/benchmarks.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/benchmarks.md).
116
+
117
+ - **Safe edits, proven.** When a file changed between read and write, skyline refused the edit
118
+ rather than overwriting it. A plain string-matching editor has no such guard.
119
+ - **Refactors that respect code.** Rewriting a Go call changed 18 of 18 real call sites and
120
+ left an identical word inside a comment untouched. A `sed` find-and-replace would have
121
+ corrupted that comment.
122
+ - **No search penalty.** A controlled query returned the same 66 matches as ripgrep, because
123
+ skyline uses the same engine and gitignore-aware walk.
124
+ - **No startup tax.** The warm daemon answers in 10 to 40 ms with no per-session startup, while
125
+ spawning the tool per session costs about a second each time.
126
+
127
+ ## Tools
128
+
129
+ skyline is one Rust binary with two faces: a command-line tool and an MCP server for AI clients.
130
+
131
+ | Capability | CLI | MCP tool |
132
+ |------------|-----|----------|
133
+ | Read a file with a content fingerprint | `skyline read` | `skyline_read` |
134
+ | Apply a fingerprint-guarded edit | `skyline edit` | `skyline_edit` |
135
+ | Patch format reference | `skyline preview` | `skyline_format` |
136
+ | Regex search (ripgrep engine) | `skyline grep` | `skyline_grep` |
137
+ | Structural search (ast-grep) | `skyline sgrep` | `skyline_sgrep` |
138
+ | Structural rewrite (ast-grep) | `skyline srewrite` | `skyline_srewrite` |
139
+ | Where a symbol is defined | | `skyline_definition` |
140
+ | Every real caller of a symbol | | `skyline_references` |
141
+ | Rename a symbol everywhere, safely | | `skyline_rename` |
142
+ | Find a symbol by name fragment | | `skyline_symbols` |
143
+ | Does the file still compile after an edit | | `skyline_diagnostics` |
144
+ | Project shape / orientation (tree) | | `skyline_tree` |
145
+ | Git status and compressed diff with anchors | | `skyline_git` |
146
+ | Run tests, failures-only with anchors | | `skyline_test` |
147
+ | Version and tool-manifest digest | `skyline version` | `skyline_version` |
148
+ | Observability streams (audit, devlog, bench) | `skyline audit/devlog/bench` | `skyline_observability_*`, tail and prune tools |
149
+ | Manage the background daemon | `skyline daemon …` | (CLI) |
150
+ | Start the daemon on every boot | `skyline daemon install` | (CLI) |
151
+ | Health check | `skyline doctor` | (CLI) |
152
+ ### Understanding code, not just matching text
153
+
154
+ The five symbol tools (`definition`, `references`, `rename`, `symbols`,
155
+ `diagnostics`) answer questions text search cannot: where a function is really
156
+ defined, who actually calls it (the same word in a comment does not count), and
157
+ how to rename it everywhere in one safe step. skyline does this by talking to
158
+ the same "language brain" your editor uses (a language server). Two things to
159
+ know: that brain is a separate program installed once per language, and skyline
160
+ prints the exact install command if it is missing; and the first question in a
161
+ project takes a few seconds while the brain reads your code, after which answers
162
+ are instant. Setup and details: [docs/lsp.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/lsp.md).
163
+ ### Language support
164
+ | Language | Extensions | sgrep/srewrite | LSP (definition, rename...) | Block ops | Test runners |
165
+ |----------|------------|:--------------:|:---------------------------:|:---------:|--------------|
166
+ | Rust | `.rs` | yes | rust-analyzer | yes | cargo-test |
167
+ | Go | `.go` | yes | gopls | yes | go-test |
168
+ | TypeScript | `.ts .tsx .mts .cts` | yes | typescript-language-server | yes | vitest, jest |
169
+ | JavaScript | `.js .jsx .mjs .cjs` | yes | typescript-language-server | yes | vitest, jest |
170
+ | Python | `.py .pyi` | yes | pyright-langserver | yes | pytest |
171
+ | PHP | `.php` | yes | intelephense / phpactor | yes | pest, phpunit |
172
+ | C | `.c .h` | yes | clangd | yes | |
173
+ | C++ | `.cc .cpp .cxx .hh .hpp .hxx` | yes | clangd | yes | |
174
+ | Ruby | `.rb` | yes | ruby-lsp | yes | rspec, rake-test |
175
+ | Java | `.java` | yes | jdtls | yes | |
176
+ | Swift | `.swift` | yes | sourcekit-lsp | yes | swift-test |
177
+ | Kotlin | `.kt .kts` | yes | kotlin-language-server | yes | |
178
+ | HTML | `.html .htm` | yes | | | |
179
+ | JSON | `.json` | yes | | | |
180
+ | YAML | `.yaml .yml` | yes | yaml-language-server | | |
181
+ | CSS | `.css` | yes | | | |
182
+ | Markdown | `.md .mdx .markdown` | | marksman | | |
183
+ Adding a language: [docs/add-a-language.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/add-a-language.md).
184
+ ## How it works
185
+
186
+ `read` prints a file with a `¶path#TAG` header and numbered lines. That header is the edit
187
+ anchor: pass it back verbatim to `edit`. The tag is a 4-hex CRC32 of the normalized content,
188
+ so a changed file produces a different tag and a stale edit is rejected (and recovered via
189
+ 3-way merge when possible). `grep` and `sgrep` return the same `¶path#TAG` headers, so search
190
+ output feeds straight into an edit. `srewrite` rewrites by structure in one pass and can
191
+ preview with `--dry-run`.
192
+
193
+ Details: [edit and patch format](https://github.com/skylence-be/binary-skyline/blob/main/docs/patch-format.md), [grep](https://github.com/skylence-be/binary-skyline/blob/main/docs/grep.md),
194
+ [structural search and rewrite](https://github.com/skylence-be/binary-skyline/blob/main/docs/sgrep.md), [the content tag](https://github.com/skylence-be/binary-skyline/blob/main/docs/content-hash.md),
195
+ [stale-edit recovery](https://github.com/skylence-be/binary-skyline/blob/main/docs/recovery.md).
196
+
197
+ ## Documentation
198
+
199
+ - [docs/install.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/install.md): all install methods
200
+ - [docs/benchmarks.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/benchmarks.md): benchmarks, findings, and methodology
201
+ - [docs/cli.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/cli.md): full CLI reference, including `daemon`, `doctor`, `version`
202
+ - [docs/mcp.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/mcp.md): MCP server, transports, client config, and tool descriptions
203
+ - [docs/grep.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/grep.md): grep reference (flags, output format, parallelism)
204
+ - [docs/sgrep.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/sgrep.md): structural search and rewrite reference
205
+ - [docs/lsp.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/lsp.md): the semantic tools (definition, references, rename, symbols, diagnostics)
206
+ - [docs/patch-format.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/patch-format.md): patch sections and operations
207
+ - [docs/content-hash.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/content-hash.md): the CRC32 content tag
208
+ - [docs/block-operations.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/block-operations.md): tree-sitter `replace block` / `delete block`
209
+ - [docs/add-a-language.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/add-a-language.md): how to wire a new language into the registry
210
+ - [docs/recovery.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/recovery.md): stale-tag recovery and snapshot storage
211
+ - [docs/observability.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/observability.md): audit, devlog, and bench streams
212
+ - [docs/npm-distribution.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/npm-distribution.md): how skyline ships to npm
213
+ - [AGENTS.md](AGENTS.md): agent-facing conventions
214
+
215
+ ## More benchmarks
216
+
217
+ From a blind production run (1.0.10, fresh agent, hugo's 896 Go files; all numbers
218
+ from skyline's own `bench` stream):
219
+
220
+ - All six tasks (a 7-file semantic rename, workspace symbol search, two repo-wide
221
+ structural counts, a YAML rule diagnosis, and the 213-file rewrite) cost
222
+ **~16.8k output tokens total**. An earlier release spent 86k on a single rewrite
223
+ preview alone; the summary preview cut that by ~99.7%.
224
+ - Per-edit cost is **flat against file size**: ~49 tokens on a 292-line file, ~62 on a
225
+ 10,496-line file. The naive read-then-edit flow grows linearly (~2.1k → ~83.5k); even
226
+ a skilled grep→windowed-read→edit flow runs 12-17× skyline's cost.
227
+ - Batched diagnostics covered 7 renamed files in **one call (~248 tokens)**. The
228
+ one-time language-server cold index on a ~224k-line workspace took 95 s; warm calls
229
+ are sub-second.
230
+ - Edit input has held at **~57 tokens p50 across releases**: anchors keep file content
231
+ out of the edit round-trip entirely.
232
+
233
+ Full tables, the 1.0.5 safety/parity/transport baselines, and honest caveats:
234
+ [docs/benchmarks.md](https://github.com/skylence-be/binary-skyline/blob/main/docs/benchmarks.md).
235
+
236
+ ## License
237
+
238
+ Apache-2.0. See [LICENSE](https://github.com/skylence-be/binary-skyline/blob/main/LICENSE).
package/bin.js ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const { spawnSync } = require("child_process");
5
+ const path = require("path");
6
+
7
+ const PLATFORM_PKGS = {
8
+ "darwin-arm64": "@skylence-ai/skyline-darwin-arm64",
9
+ "darwin-x64": "@skylence-ai/skyline-darwin-x64",
10
+ "linux-arm64": "@skylence-ai/skyline-linux-arm64",
11
+ "linux-x64": "@skylence-ai/skyline-linux-x64",
12
+ "win32-x64": "@skylence-ai/skyline-win32-x64",
13
+ "win32-arm64": "@skylence-ai/skyline-win32-arm64",
14
+ };
15
+
16
+ function getBinaryPath() {
17
+ const arch = process.arch === "arm64" ? "arm64" : "x64";
18
+ const key = `${process.platform}-${arch}`;
19
+ const pkg = PLATFORM_PKGS[key];
20
+ if (!pkg) {
21
+ throw new Error(
22
+ `skyline: unsupported platform: ${process.platform} ${process.arch}\n` +
23
+ `Supported: ${Object.keys(PLATFORM_PKGS).join(", ")}`
24
+ );
25
+ }
26
+ let pkgDir;
27
+ try {
28
+ pkgDir = path.dirname(require.resolve(`${pkg}/package.json`));
29
+ } catch {
30
+ throw new Error(
31
+ `skyline: platform package ${pkg} is not installed.\n` +
32
+ `Run: npm install ${pkg}`
33
+ );
34
+ }
35
+ const ext = process.platform === "win32" ? ".exe" : "";
36
+ return path.join(pkgDir, `skyline${ext}`);
37
+ }
38
+
39
+ let binaryPath;
40
+ try {
41
+ binaryPath = getBinaryPath();
42
+ } catch (err) {
43
+ process.stderr.write(err.message + "\n");
44
+ process.exit(1);
45
+ }
46
+
47
+ const result = spawnSync(binaryPath, process.argv.slice(2), { stdio: "inherit" });
48
+ process.exit(result.status ?? 1);
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@skylence-ai/skyline",
3
+ "version": "1.0.31",
4
+ "description": "Content-hash line editor — CLI and MCP server",
5
+ "license": "Apache-2.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/skylence-be/binary-skyline"
9
+ },
10
+ "bugs": "https://github.com/skylence-be/binary-skyline/issues",
11
+ "homepage": "https://github.com/skylence-be/binary-skyline#readme",
12
+ "keywords": [
13
+ "mcp",
14
+ "editor",
15
+ "hash",
16
+ "search",
17
+ "ast-grep",
18
+ "cli"
19
+ ],
20
+ "engines": {
21
+ "node": ">=16"
22
+ },
23
+ "preferUnplugged": true,
24
+ "bin": {
25
+ "skyline": "bin.js"
26
+ },
27
+ "optionalDependencies": {
28
+ "@skylence-ai/skyline-darwin-arm64": "1.0.31",
29
+ "@skylence-ai/skyline-darwin-x64": "1.0.31",
30
+ "@skylence-ai/skyline-linux-arm64": "1.0.31",
31
+ "@skylence-ai/skyline-linux-x64": "1.0.31",
32
+ "@skylence-ai/skyline-win32-x64": "1.0.31"
33
+ }
34
+ }