@youtyan/code-viewer 0.2.10 → 0.2.11

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.
package/README.md CHANGED
@@ -27,8 +27,9 @@ Requires Node.js 20 or newer when installed from npm. Development uses
27
27
  viewer.
28
28
  - Browse SQLite, PostgreSQL, MySQL, Redis, Elasticsearch, and S3-compatible
29
29
  object storage (MinIO, LocalStack) with a built-in datastore viewer.
30
- - Read the built-in Help page for repository browsing, diffs, annotations,
31
- the datastore viewer, agent skills, and shortcuts.
30
+ - Read the built-in Help page for getting started, the `.code-viewer/`
31
+ project files, AI annotations, datastores, the agent skill, and
32
+ keybindings.
32
33
  - Open repository folders (and parent folders of files) in the OS file
33
34
  manager, create folders, and trash/restore files from localhost-only
34
35
  actions.
@@ -239,9 +240,10 @@ Open Datastores in the global navigation to access:
239
240
 
240
241
  ### CLI
241
242
 
242
- AI agents can read data and query history from the command line. The current
243
- CLI ships `exec`, `list`, and `clear`; search, snapshot, and diff operations
244
- are performed from the browser UI.
243
+ AI agents can run read-only queries, search content across tables, and
244
+ capture snapshots / diffs from the command line. The same operations are
245
+ mirrored under the Datastores tab in the browser UI, and every CLI result is
246
+ written to the per-repository history visible in the browser.
245
247
 
246
248
  ```sh
247
249
  code-viewer query exec --db data.db --sql "SELECT * FROM users LIMIT 10" \
@@ -252,6 +254,22 @@ code-viewer query exec --db app.db --sql "SELECT count(*) FROM orders" \
252
254
 
253
255
  code-viewer query list --db app.db --json
254
256
  code-viewer query clear --db app.db
257
+
258
+ code-viewer query search --db app.db --term "john@example.com" \
259
+ --tables users,orders --include-non-text --max-hits 20
260
+
261
+ code-viewer query snapshot create --db app.db --tables users,orders \
262
+ --note "Before user registration test"
263
+ code-viewer query snapshot list --db app.db --json
264
+ code-viewer query snapshot note --id snap-abc123 --note "Updated context"
265
+ code-viewer query snapshot delete --id snap-abc123
266
+
267
+ code-viewer query diff create --before snap-abc123 --after snap-def456 \
268
+ --note "User registration test"
269
+ code-viewer query diff tables --id diff-xyz789
270
+ code-viewer query diff rows --id diff-xyz789 --table users --type inserted
271
+ code-viewer query diff list --db app.db --json
272
+ code-viewer query diff delete --id diff-xyz789
255
273
  ```
256
274
 
257
275
  `code-viewer query --help` shows all command syntax. `code-viewer query
@@ -307,9 +325,9 @@ with `--include-non-text` and `--run-search`. For AI agents,
307
325
 
308
326
  Annotations are grouped into sessions and persisted in
309
327
  `.code-viewer/annotations.json` at the repository root, so the walkthrough
310
- survives reloads and server restarts. The `.code-viewer` directory is
311
- tool-internal: it never shows up in the file tree, searches, or diffs. Add it
312
- to `.gitignore` if you do not want to share annotations through git.
328
+ survives reloads and server restarts. See **Uploads and Scope Settings**
329
+ above for how `.code-viewer/` is treated by the viewer and how to opt out of
330
+ sharing it through git.
313
331
 
314
332
  In the browser, the annotation icon in the header opens the side panel. The
315
333
  current explanation is rendered at the top of the panel while the code stays
@@ -341,9 +359,11 @@ write concise Markdown explanations, and how to install the bundled agent skill.
341
359
 
342
360
  ### Agent Skill
343
361
 
344
- The package bundles [Agent Skills](https://agentskills.io) (the SKILL.md
345
- open standard) that teach AI coding agents when and how to use
346
- `annotate`, `query`, and `snapshot`. Install them into the current project:
362
+ The package bundles three [Agent Skills](https://agentskills.io)
363
+ (the SKILL.md open standard) `code-viewer-annotate`, `code-viewer-query`,
364
+ and `code-viewer-snapshot` that teach AI coding agents when and how to use
365
+ `annotate`, read-only `query`, and snapshot / diff workflows. A single
366
+ `skill install` copies all three into the selected agent directories:
347
367
 
348
368
  ```sh
349
369
  npx -y @youtyan/code-viewer skill install # Claude Code (.claude/skills/)
@@ -2775,7 +2775,7 @@ __export(exports_skill_cli, {
2775
2775
  SKILL_HELP: () => SKILL_HELP,
2776
2776
  AGENT_SKILL_DIRS: () => AGENT_SKILL_DIRS
2777
2777
  });
2778
- import { cpSync, existsSync as existsSync4, mkdirSync as mkdirSync2 } from "node:fs";
2778
+ import { cpSync, existsSync as existsSync4, mkdirSync as mkdirSync2, readdirSync as readdirSync2 } from "node:fs";
2779
2779
  import { homedir as homedir2 } from "node:os";
2780
2780
  import { join as join5, resolve } from "node:path";
2781
2781
  function parseAgentList(value) {
@@ -2831,25 +2831,34 @@ function parseSkillArgs(argv) {
2831
2831
  }
2832
2832
  return { ok: true, args: { kind: "install", agents, global, cwd } };
2833
2833
  }
2834
+ function discoverBundledSkills(skillsRoot) {
2835
+ if (!existsSync4(skillsRoot))
2836
+ return [];
2837
+ return readdirSync2(skillsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && existsSync4(join5(skillsRoot, entry.name, "SKILL.md"))).map((entry) => entry.name).sort();
2838
+ }
2834
2839
  function installSkill(args, deps) {
2835
- if (!existsSync4(join5(deps.sourceDir, "SKILL.md"))) {
2840
+ const skills = discoverBundledSkills(deps.skillsRoot);
2841
+ if (skills.length === 0) {
2836
2842
  return {
2837
2843
  ok: false,
2838
- error: `bundled skill not found at ${deps.sourceDir}`
2844
+ error: `no bundled skills found under ${deps.skillsRoot}`
2839
2845
  };
2840
2846
  }
2841
2847
  const base = args.global ? deps.homeDir : resolve(args.cwd ?? deps.projectDir);
2842
2848
  const results = [];
2843
2849
  for (const agent of args.agents) {
2844
- const target = join5(base, AGENT_SKILL_DIRS[agent], "skills", SKILL_NAME);
2845
- const action = existsSync4(target) ? "updated" : "installed";
2846
- try {
2847
- mkdirSync2(target, { recursive: true });
2848
- cpSync(deps.sourceDir, target, { recursive: true });
2849
- } catch (error) {
2850
- return { ok: false, error: String(error) };
2850
+ for (const skill of skills) {
2851
+ const sourceDir = join5(deps.skillsRoot, skill);
2852
+ const target = join5(base, AGENT_SKILL_DIRS[agent], "skills", skill);
2853
+ const action = existsSync4(target) ? "updated" : "installed";
2854
+ try {
2855
+ mkdirSync2(target, { recursive: true });
2856
+ cpSync(sourceDir, target, { recursive: true });
2857
+ } catch (error) {
2858
+ return { ok: false, error: String(error) };
2859
+ }
2860
+ results.push({ agent, skill, action, target });
2851
2861
  }
2852
- results.push({ agent, action, target });
2853
2862
  }
2854
2863
  return { ok: true, results };
2855
2864
  }
@@ -2865,7 +2874,7 @@ function runSkillCli(argv) {
2865
2874
  return;
2866
2875
  }
2867
2876
  const result = installSkill(parsed.args, {
2868
- sourceDir: join5(ROOT, "skills", SKILL_NAME),
2877
+ skillsRoot: join5(ROOT, "skills"),
2869
2878
  homeDir: homedir2(),
2870
2879
  projectDir: process.cwd()
2871
2880
  });
@@ -2874,13 +2883,13 @@ function runSkillCli(argv) {
2874
2883
  process.exit(1);
2875
2884
  }
2876
2885
  for (const entry of result.results) {
2877
- console.log(`${entry.action} (${entry.agent}): ${entry.target}`);
2886
+ console.log(`${entry.action} (${entry.agent}/${entry.skill}): ${entry.target}`);
2878
2887
  }
2879
2888
  if (result.results.some((entry) => entry.action === "installed")) {
2880
- console.log("Re-run the same command anytime to update the skill.");
2889
+ console.log("Re-run the same command anytime to update the skills.");
2881
2890
  }
2882
2891
  }
2883
- var SKILL_NAME = "code-viewer-annotate", AGENT_SKILL_DIRS, AGENT_NAMES, SKILL_HELP;
2892
+ var AGENT_SKILL_DIRS, AGENT_NAMES, SKILL_HELP;
2884
2893
  var init_skill_cli = __esm(() => {
2885
2894
  init_root();
2886
2895
  AGENT_SKILL_DIRS = {
@@ -2891,15 +2900,16 @@ var init_skill_cli = __esm(() => {
2891
2900
  agents: ".agents"
2892
2901
  };
2893
2902
  AGENT_NAMES = Object.keys(AGENT_SKILL_DIRS);
2894
- SKILL_HELP = `code-viewer skill — manage the bundled agent skill
2903
+ SKILL_HELP = `code-viewer skill — manage the bundled agent skills
2895
2904
 
2896
2905
  Usage:
2897
2906
  code-viewer skill install [--agent <list>] [--global] [--cwd <dir>]
2898
2907
 
2899
- Installs the ${SKILL_NAME} skill (SKILL.md for AI coding agents) into the
2900
- skills directory of each selected agent in the current project, or into the
2901
- home directory equivalents with --global. Running install again overwrites
2902
- the files, so the same command also updates an existing installation.
2908
+ Installs every bundled skill (each SKILL.md directory under the package's
2909
+ skills/) into the skills directory of each selected agent in the current
2910
+ project, or into the home directory equivalents with --global. Running
2911
+ install again overwrites the files, so the same command also updates an
2912
+ existing installation.
2903
2913
 
2904
2914
  Options:
2905
2915
  --agent <list> comma separated agents: ${AGENT_NAMES.join(", ")}, or all
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@youtyan/code-viewer",
3
- "version": "0.2.10",
3
+ "version": "0.2.11",
4
4
  "description": "Local browser-based code and git diff viewer",
5
5
  "type": "module",
6
6
  "bin": {
package/web/app.js CHANGED
@@ -18383,6 +18383,7 @@ ${frontmatter.yaml}
18383
18383
  var HELP_LANGUAGES = ["en", "ja"];
18384
18384
  var HELP_SECTIONS = [
18385
18385
  "overview",
18386
+ "storage",
18386
18387
  "annotations",
18387
18388
  "database",
18388
18389
  "skills",
@@ -18461,6 +18462,73 @@ ${frontmatter.yaml}
18461
18462
  }
18462
18463
  ]
18463
18464
  },
18465
+ storage: {
18466
+ nav: "Project Files",
18467
+ title: ".code-viewer Directory",
18468
+ intro: "code-viewer keeps every per-repository state file under .code-viewer/ at the root of the opened repository. The directory is created on demand, can be deleted at any time to reset state, and should be gitignored in most projects.",
18469
+ groups: [
18470
+ {
18471
+ title: "What lives there",
18472
+ blocks: [
18473
+ {
18474
+ kind: "table",
18475
+ rows: [
18476
+ [
18477
+ "settings.json",
18478
+ "Viewer Settings — diff layout, theme, language, sidebar/history widths, font sizes, syntax highlight, ignore-whitespace, hide-tests, scope overrides (omitted dirs / excluded names), upload toggle, annotation panel open/follow/mute/rate, and the last viewed diff range."
18479
+ ],
18480
+ [
18481
+ "view-state.json",
18482
+ "Sidebar tree state — collapsed directories, lazy-expanded directories (folders opened on demand in large repos), and the viewed-file list used to dim already-read entries."
18483
+ ],
18484
+ [
18485
+ "tabs.json",
18486
+ "Multi-DB tab layout — open datastore tabs, the active tab, per-tab selected table / view / SQL draft, per-tab Elasticsearch index and Redis DB index, and per-tab sidebar and history panel widths."
18487
+ ],
18488
+ [
18489
+ "db-ui.json",
18490
+ "Datastore UI preferences — column widths per (DB, table, column) and toggle states such as Rails FK inference and the S3 tooltip."
18491
+ ],
18492
+ [
18493
+ "annotations.json",
18494
+ "AI annotation walkthroughs — sessions with their ordered steps (file, line range, title, body), used by the annotation panel and synced live to open tabs over SSE."
18495
+ ],
18496
+ [
18497
+ "query-history.json",
18498
+ "SQL query history — recent statements with column list, preview rows, row count, elapsed time, executor (browser or CLI), and execution timestamp."
18499
+ ],
18500
+ [
18501
+ "db-snapshots.sqlite (+ -shm / -wal)",
18502
+ "SQLite store used by the Datastore Snapshot tab to keep point-in-time captures of tables / indices / key spaces for diffing. The -shm / -wal sidecar files are SQLite WAL artifacts; do not edit them directly."
18503
+ ]
18504
+ ]
18505
+ }
18506
+ ]
18507
+ },
18508
+ {
18509
+ title: "Source of truth and editing",
18510
+ blocks: [
18511
+ {
18512
+ kind: "paragraph",
18513
+ text: "Everything in .code-viewer/ is owned by code-viewer. JSON files are rewritten safely with validation on every change, so unknown keys are dropped and invalid values are reset to defaults. Hand-edit at your own risk — a corrupt file is renamed with a .corrupt suffix and replaced with an empty default."
18514
+ },
18515
+ {
18516
+ kind: "paragraph",
18517
+ text: "Deleting the whole directory is the supported way to reset all per-repository state. Removing a single file resets only that subsystem (for example, deleting tabs.json closes all DB tabs on the next load)."
18518
+ }
18519
+ ]
18520
+ },
18521
+ {
18522
+ title: "Sharing across machines",
18523
+ blocks: [
18524
+ {
18525
+ kind: "paragraph",
18526
+ text: "These files contain local UI state and should normally stay out of version control — add .code-viewer/ to .gitignore. To share AI walkthroughs, commit annotations.json explicitly (or copy it between checkouts) and leave the other files ignored."
18527
+ }
18528
+ ]
18529
+ }
18530
+ ]
18531
+ },
18464
18532
  annotations: {
18465
18533
  nav: "AI Annotations",
18466
18534
  title: "AI Code Annotations",
@@ -18683,7 +18751,7 @@ code-viewer annotate add-db --db app.db --tab query \\
18683
18751
  blocks: [
18684
18752
  {
18685
18753
  kind: "paragraph",
18686
- text: "AI agents can execute read-only queries and manage per-DB query history from the CLI. Results are saved into the same history visible in the browser. Search, snapshot, and diff operations live in the browser UI (Search tab / Snapshot tab) rather than the CLI."
18754
+ text: "AI agents can execute read-only queries, search across tables, and capture snapshots / diffs from the CLI. Results are written to the same per-repository history visible in the browser, and the browser UI exposes the same operations through the Search tab and the Snapshot tab."
18687
18755
  },
18688
18756
  {
18689
18757
  kind: "command",
@@ -18700,6 +18768,37 @@ code-viewer annotate add-db --db app.db --tab query \\
18700
18768
  title: "List or clear query history",
18701
18769
  command: `code-viewer query list --db app.db --json
18702
18770
  code-viewer query clear --db app.db`
18771
+ },
18772
+ {
18773
+ kind: "command",
18774
+ title: "Search across all tables",
18775
+ command: 'code-viewer query search --db app.db --term "john@example.com" \\\n --tables users,orders --include-non-text --max-hits 20'
18776
+ },
18777
+ {
18778
+ kind: "command",
18779
+ title: "Capture a snapshot",
18780
+ command: 'code-viewer query snapshot create --db app.db --tables users,orders \\\n --note "Before user registration test"'
18781
+ },
18782
+ {
18783
+ kind: "command",
18784
+ title: "List, annotate, or delete snapshots",
18785
+ command: `code-viewer query snapshot list --db app.db --json
18786
+ code-viewer query snapshot note --id snap-abc123 --note "Updated context"
18787
+ code-viewer query snapshot delete --id snap-abc123`
18788
+ },
18789
+ {
18790
+ kind: "command",
18791
+ title: "Diff two snapshots",
18792
+ command: `code-viewer query diff create --before snap-abc123 --after snap-def456 \\
18793
+ --note "User registration test"
18794
+ code-viewer query diff list --db app.db --json
18795
+ code-viewer query diff delete --id diff-xyz789`
18796
+ },
18797
+ {
18798
+ kind: "command",
18799
+ title: "Inspect a diff",
18800
+ command: `code-viewer query diff tables --id diff-xyz789
18801
+ code-viewer query diff rows --id diff-xyz789 --table users --type inserted --limit 50`
18703
18802
  },
18704
18803
  {
18705
18804
  kind: "command",
@@ -18713,10 +18812,10 @@ code-viewer query clear --db app.db`
18713
18812
  skills: {
18714
18813
  nav: "Agent Skill",
18715
18814
  title: "Agent Skill Setup",
18716
- intro: "The package includes a code-viewer annotate skill so AI agents know when and how to create browser walkthroughs.",
18815
+ intro: "The package bundles three skills — code-viewer-annotate, code-viewer-query, and code-viewer-snapshot — so AI agents know when and how to create browser walkthroughs, run read-only queries, and capture snapshot / diff sessions. A single skill install command copies all three into the selected agent directories.",
18717
18816
  groups: [
18718
18817
  {
18719
- title: "Install the skill",
18818
+ title: "Install the skills",
18720
18819
  blocks: [
18721
18820
  {
18722
18821
  kind: "command",
@@ -18738,11 +18837,17 @@ code-viewer query clear --db app.db`
18738
18837
  kind: "command",
18739
18838
  title: "Install globally for a user (not per project)",
18740
18839
  command: "npx -y @youtyan/code-viewer skill install --agent all --global"
18840
+ },
18841
+ {
18842
+ kind: "command",
18843
+ title: "Install into a different project directory",
18844
+ command: `npx -y @youtyan/code-viewer skill install --agent all --cwd /path/to/other/repo
18845
+ # --cwd selects the target project; ignored when --global is also given.`
18741
18846
  }
18742
18847
  ]
18743
18848
  },
18744
18849
  {
18745
- title: "What the skill teaches",
18850
+ title: "What the skills teach",
18746
18851
  blocks: [
18747
18852
  {
18748
18853
  kind: "table",
@@ -18916,6 +19021,73 @@ code-viewer query clear --db app.db`
18916
19021
  }
18917
19022
  ]
18918
19023
  },
19024
+ storage: {
19025
+ nav: "プロジェクトファイル",
19026
+ title: ".code-viewer ディレクトリ",
19027
+ intro: "code-viewer はリポジトリ単位の状態をすべて、開いたリポジトリ直下の .code-viewer/ ディレクトリに保存します。必要になったときに自動で作られ、削除すれば全状態をリセットでき、通常は .gitignore に登録しておきます。",
19028
+ groups: [
19029
+ {
19030
+ title: "中に置かれるファイル",
19031
+ blocks: [
19032
+ {
19033
+ kind: "table",
19034
+ rows: [
19035
+ [
19036
+ "settings.json",
19037
+ "Viewer Settings — diff レイアウト、テーマ、言語、サイドバー/履歴幅、フォントサイズ、シンタックスハイライト、whitespace 無視、テスト非表示、scope 上書き(除外ディレクトリ / 除外名)、アップロード許可、注釈パネルの開閉/follow/ミュート/再生速度、最後に表示した diff 範囲を保存します。"
19038
+ ],
19039
+ [
19040
+ "view-state.json",
19041
+ "サイドバーツリーの状態 — 折りたたみ済みディレクトリ、遅延展開済みディレクトリ(大規模リポジトリで必要に応じて開かれたフォルダ)、既読扱いするための表示済みファイル一覧。"
19042
+ ],
19043
+ [
19044
+ "tabs.json",
19045
+ "マルチ DB タブのレイアウト — 開いているデータストアタブ、アクティブタブ、タブごとの選択テーブル / ビュー / SQL ドラフト、Elasticsearch のインデックスや Redis の DB index、タブ単位のサイドバー幅・履歴パネル高。"
19046
+ ],
19047
+ [
19048
+ "db-ui.json",
19049
+ "データストア UI の設定 — (DB, テーブル, カラム) ごとの列幅、Rails FK 推測や S3 ツールチップなどのトグル状態。"
19050
+ ],
19051
+ [
19052
+ "annotations.json",
19053
+ "AI 注釈のウォークスルー — セッションと順序付きステップ(ファイル、行範囲、タイトル、本文)。注釈パネルが読み、SSE で開いているタブへもライブ同期されます。"
19054
+ ],
19055
+ [
19056
+ "query-history.json",
19057
+ "SQL クエリ履歴 — 直近のクエリ、カラム一覧、プレビュー行、行数、実行時間、実行元(browser / CLI)、実行時刻。"
19058
+ ],
19059
+ [
19060
+ "db-snapshots.sqlite (+ -shm / -wal)",
19061
+ "Snapshot タブが使う SQLite ストア。テーブル / インデックス / キー空間の時点スナップショットを保持し、差分表示に使います。-shm / -wal は SQLite の WAL 用付随ファイル。手動編集しないでください。"
19062
+ ]
19063
+ ]
19064
+ }
19065
+ ]
19066
+ },
19067
+ {
19068
+ title: "ファイルの所有権と編集",
19069
+ blocks: [
19070
+ {
19071
+ kind: "paragraph",
19072
+ text: ".code-viewer/ の中身はすべて code-viewer が管理します。JSON ファイルは書き込みごとにバリデーションを通して安全に書き換えられるため、未知のキーは破棄され、不正な値は既定値に戻されます。手で編集すると壊れる可能性があり、壊れたファイルは .corrupt サフィックスに改名されて空の既定値で置き換えられます。"
19073
+ },
19074
+ {
19075
+ kind: "paragraph",
19076
+ text: "ディレクトリごと削除するのが、このリポジトリの全状態をリセットする推奨手順です。個別ファイルだけを消した場合はその系統だけがリセットされます(例: tabs.json を消すと次回起動時に DB タブがすべて閉じた状態になります)。"
19077
+ }
19078
+ ]
19079
+ },
19080
+ {
19081
+ title: "他マシンとの共有",
19082
+ blocks: [
19083
+ {
19084
+ kind: "paragraph",
19085
+ text: "これらはローカル UI 状態なので、原則としてバージョン管理には入れません — .code-viewer/ を .gitignore に追加しておきます。AI のウォークスルーを共有したい場合は annotations.json だけを明示的に commit(または別チェックアウトへコピー)し、それ以外は無視したままにします。"
19086
+ }
19087
+ ]
19088
+ }
19089
+ ]
19090
+ },
18919
19091
  annotations: {
18920
19092
  nav: "AI注釈",
18921
19093
  title: "AI コード注釈",
@@ -19138,7 +19310,7 @@ code-viewer annotate add-db --db app.db --tab query \\
19138
19310
  blocks: [
19139
19311
  {
19140
19312
  kind: "paragraph",
19141
- text: "AI エージェントは CLI から read-only クエリの実行と per-DB クエリ履歴の管理ができます。結果はブラウザでも見える同じ履歴に保存されます。Search / Snapshot / Diff は CLI ではなくブラウザ UI Search タブ / Snapshot タブから操作します。"
19313
+ text: "AI エージェントは CLI から read-only クエリの実行、テーブル横断検索、スナップショット / 差分作成までできます。結果はブラウザで見えるのと同じリポジトリ単位の履歴に保存され、ブラウザ UI 側でも Search タブ / Snapshot タブから同じ操作が行えます。"
19142
19314
  },
19143
19315
  {
19144
19316
  kind: "command",
@@ -19152,9 +19324,40 @@ code-viewer annotate add-db --db app.db --tab query \\
19152
19324
  },
19153
19325
  {
19154
19326
  kind: "command",
19155
- title: "履歴の一覧/削除",
19327
+ title: "履歴の一覧 / 削除",
19156
19328
  command: `code-viewer query list --db app.db --json
19157
19329
  code-viewer query clear --db app.db`
19330
+ },
19331
+ {
19332
+ kind: "command",
19333
+ title: "テーブル横断の全文検索",
19334
+ command: 'code-viewer query search --db app.db --term "john@example.com" \\\n --tables users,orders --include-non-text --max-hits 20'
19335
+ },
19336
+ {
19337
+ kind: "command",
19338
+ title: "スナップショットを作成",
19339
+ command: 'code-viewer query snapshot create --db app.db --tables users,orders \\\n --note "ユーザー登録テスト前"'
19340
+ },
19341
+ {
19342
+ kind: "command",
19343
+ title: "スナップショットの一覧 / メモ更新 / 削除",
19344
+ command: `code-viewer query snapshot list --db app.db --json
19345
+ code-viewer query snapshot note --id snap-abc123 --note "メモを更新"
19346
+ code-viewer query snapshot delete --id snap-abc123`
19347
+ },
19348
+ {
19349
+ kind: "command",
19350
+ title: "2 つのスナップショットを diff",
19351
+ command: `code-viewer query diff create --before snap-abc123 --after snap-def456 \\
19352
+ --note "ユーザー登録テストの差分"
19353
+ code-viewer query diff list --db app.db --json
19354
+ code-viewer query diff delete --id diff-xyz789`
19355
+ },
19356
+ {
19357
+ kind: "command",
19358
+ title: "diff の中身を確認",
19359
+ command: `code-viewer query diff tables --id diff-xyz789
19360
+ code-viewer query diff rows --id diff-xyz789 --table users --type inserted --limit 50`
19158
19361
  },
19159
19362
  {
19160
19363
  kind: "command",
@@ -19168,7 +19371,7 @@ code-viewer query clear --db app.db`
19168
19371
  skills: {
19169
19372
  nav: "スキル登録",
19170
19373
  title: "Agent Skill の登録",
19171
- intro: "このパッケージには、AI エージェントが code-viewer annotate 機能を正しく使うためのスキルが同梱されています。",
19374
+ intro: "このパッケージには 3 つのスキル (code-viewer-annotate / code-viewer-query / code-viewer-snapshot) が同梱されており、AI エージェントに annotate でのウォークスルー、read-only な query、スナップショット / 差分の使い分けを教えます。skill install を 1 回叩くと、選んだエージェントすべてに 3 スキルがコピーされます。",
19172
19375
  groups: [
19173
19376
  {
19174
19377
  title: "スキルをインストールする",
@@ -19193,6 +19396,12 @@ code-viewer query clear --db app.db`
19193
19396
  kind: "command",
19194
19397
  title: "ユーザー全体(プロジェクト外)へ登録",
19195
19398
  command: "npx -y @youtyan/code-viewer skill install --agent all --global"
19399
+ },
19400
+ {
19401
+ kind: "command",
19402
+ title: "別プロジェクトのディレクトリへ登録",
19403
+ command: `npx -y @youtyan/code-viewer skill install --agent all --cwd /path/to/other/repo
19404
+ # --cwd でインストール先プロジェクトを指定。--global を併用したときは無視されます。`
19196
19405
  }
19197
19406
  ]
19198
19407
  },
@@ -20313,7 +20522,7 @@ code-viewer query clear --db app.db`
20313
20522
  } else {
20314
20523
  lnHtml = '<td class="d2h-code-linenumber d2h-cntx">' + '<div class="line-num1">' + (oldStart + i2) + "</div>" + '<div class="line-num2">' + (newStart + i2) + "</div>" + "</td>";
20315
20524
  }
20316
- tr.innerHTML = lnHtml + '<td class="d2h-cntx">' + '<div class="' + (isSplit ? "d2h-code-side-line" : "d2h-code-line") + '">' + '<span class="d2h-code-line-prefix">&nbsp;</span>' + '<span class="d2h-code-line-ctn">' + escapeHtmlText(lines[i2]) + "</span>" + "</div>" + "</td>";
20525
+ tr.innerHTML = lnHtml + '<td class="d2h-cntx">' + '<div class="' + (isSplit ? "d2h-code-side-line" : "d2h-code-line") + '">' + '<span class="d2h-code-line-prefix">&nbsp;</span> ' + '<span class="d2h-code-line-ctn">' + escapeHtmlText(lines[i2]) + "</span>" + "</div>" + "</td>";
20317
20526
  frag.appendChild(tr);
20318
20527
  }
20319
20528
  tbody.insertBefore(frag, anchor);
@@ -21359,7 +21568,7 @@ code-viewer query clear --db app.db`
21359
21568
  li.dataset.path = f2.path;
21360
21569
  li.dataset.type = "blob";
21361
21570
  li.classList.toggle("viewed", !onFileClick && STATE.viewedFiles.has(f2.path));
21362
- li.classList.toggle("hidden-by-tests", STATE.hideTests && isTestPath(f2.path || ""));
21571
+ li.classList.toggle("hidden-by-tests", STATE.hideTests && !isRepositorySidebarMode() && isTestPath(f2.path || ""));
21363
21572
  li.style.setProperty("--lvl-pad", `${12 + depth * 14}px`);
21364
21573
  const spacer = document.createElement("span");
21365
21574
  spacer.className = "chev-spacer";
@@ -21458,7 +21667,7 @@ code-viewer query clear --db app.db`
21458
21667
  }
21459
21668
  subtreeVisible = subtreeVisible || visible;
21460
21669
  } else {
21461
- const testHidden = STATE.hideTests && isTestPath(item.file.path || "");
21670
+ const testHidden = STATE.hideTests && !isRepositorySidebarMode() && isTestPath(item.file.path || "");
21462
21671
  const visible = !testHidden && matches(item.file.path || "");
21463
21672
  if (visible) {
21464
21673
  rows.push({
@@ -26923,6 +27132,7 @@ code-viewer query clear --db app.db`
26923
27132
  if (STATE.route.screen !== "database") {
26924
27133
  setQueryHistoryPanelOpen(false);
26925
27134
  }
27135
+ applyHideTests();
26926
27136
  }
26927
27137
  function syncHeaderMenu() {
26928
27138
  document.querySelectorAll(".app-menu-item, .global-help-link").forEach((link2) => {
@@ -27824,13 +28034,14 @@ code-viewer query clear --db app.db`
27824
28034
  const btn = $("#hide-tests");
27825
28035
  if (btn)
27826
28036
  btn.classList.toggle("active", STATE.hideTests);
28037
+ const effective = STATE.hideTests && !isRepositorySidebarMode();
27827
28038
  document.querySelectorAll(".gdp-file-shell").forEach((card) => {
27828
28039
  const isTest = TEST_RE.test(card.dataset.path || "");
27829
- card.classList.toggle("hidden-by-tests", STATE.hideTests && isTest);
28040
+ card.classList.toggle("hidden-by-tests", effective && isTest);
27830
28041
  });
27831
28042
  document.querySelectorAll("#filelist li[data-path]").forEach((li) => {
27832
28043
  const isTest = TEST_RE.test(li.dataset.path || "");
27833
- li.classList.toggle("hidden-by-tests", STATE.hideTests && isTest);
28044
+ li.classList.toggle("hidden-by-tests", effective && isTest);
27834
28045
  });
27835
28046
  if (isVirtualSidebarActive())
27836
28047
  rerenderVirtualSidebar();