diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 00000000..fe5bf664 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,37 @@ +{ + "permissions": { + "allow": [ + "Bash(git add *)", + "Bash(git commit *)", + "Bash(go *)", + "Bash(make *)", + "Bash(golangci-lint *)", + "Bash(goreleaser *)", + "Bash(govulncheck *)", + "Bash(npm *)" + ], + "deny": [ + "Bash(rm -rf /*)", + "Bash(rm -rf ~*)", + "Bash(rm -rf $HOME*)", + "Bash(sudo rm *)", + "Bash(sudo chmod *)", + "Bash(sudo chown *)", + "Bash(mkfs*)", + "Bash(mkfs.*)", + "Bash(dd if=*)", + "Bash(git push --force*)", + "Bash(git push -f*)", + "Bash(git push --force-with-lease*)", + "Bash(git reset --hard*)", + "Bash(git clean -fd*)", + "Bash(git clean -fdx*)", + "Bash(git clean -ffd*)", + "Bash(git branch -D *)", + "Bash(git checkout -- *)", + "Bash(git restore .*)", + "Bash(chmod -R 777 *)", + "Bash(chmod 777 *)" + ] + } +} diff --git a/.claude/skills/git-commit/SKILL.md b/.claude/skills/git-commit/SKILL.md new file mode 100644 index 00000000..9d653b3c --- /dev/null +++ b/.claude/skills/git-commit/SKILL.md @@ -0,0 +1,113 @@ +--- +name: git-commit +description: > + Git commit conventions for this repo — message style, changelog and + version-bump rules, attribution trailer, and the safety rules that + always apply. Use whenever the user says "commit", "commit this", + "create a commit", "make a commit", "amend", or asks Claude to check + work into git in any form. +--- + +# Git commit rule — this repo + +Follow these conventions whenever you create a commit in this repository. These are in addition to the standard Claude Code git-safety protocol (no `--no-verify`, no force-push to main, prefer new commits over `--amend`, etc.). + +## Message style + +- **First line:** imperative mood, ≤ 70 characters. Examples: `add sidecar PTY scaffold`, `fix IPC reconnect after app reload`, `update CLI exit-code contract`. +- **Body (optional):** wrap at ~72 chars. Explain the *why* — the reason this change exists. The diff already shows the *what*; don't restate it in prose. +- **No emojis.** Anywhere. +- **Don't prefix with types** like `feat:` or `fix:` — this repo isn't Conventional Commits. (The Python-era clide under `legacy/` used Conventional Commits; the Flutter rebuild at the repo root does not.) +- **Don't reference the current task or flow** (`for the v2.0 milestone`, `used by the canvas panel`) — that context belongs in the PR description and rots as the repo evolves. +- **Naming:** the project is `clide`. The Flutter desktop app lives at the repo root; the Go sidecar/CLI binary is `clide`. The supporter project is `pql` (referenced, not part of this repo). The archived Python implementation lives under `legacy/`. + +## Logically-separated commits + +Default to **one logical change per commit**, even when a lot of work lands in the tree at once. When there's a pile of uncommitted or untracked files: + +1. **Read `git status` + `git diff` first** — never stage the whole tree blind. +2. **Group by concern**, not by file location. Typical concerns to separate: + - **Bookkeeping** — `.gitignore`, editor/IDE config, lockfiles, `go.sum` / `pubspec.lock` updates. + - **Documentation** — `README.md`, `CLAUDE.md`, ADRs under `docs/ADRs/`, design notes under `docs/`. + - **General-purpose tooling / skills** — things that aren't project-specific (reusable skills, shared scripts). + - **Project-specific conventions** — this repo's own rules. + - **Feature or subsystem** — one cohesive change per commit; a sidecar change and an app change for the same feature can land together, but two unrelated features should split. + - **Layer changes** — Flutter app, sidecar CLI, sidecar daemon, IPC server, pql wrapper, canvas driver, git panel — separate concerns; prefer separate commits when the changes are independent. +3. **Sequence the commits** so each one is cleanly scoped, but don't obsess about whether each intermediate commit "works" — for scaffolding PRs it's fine if the full picture only snaps together at the end. +4. **Prefer many small focused commits over one large mixed one** — a reviewer can read, revert, or cherry-pick a focused commit; they can't do any of those to a blob. +5. **Use `git add `** — never `git add -A` or `git add .` when splitting, or you'll sweep in the next commit's work by accident. +6. **Verify between commits** with `git status` and `git log -1` to confirm the split landed as intended. + +Corollary: if a commit's subject line needs the word "and" to be accurate, it probably should have been two commits. + +## Changelog discipline + +This repo follows [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/). **Every user-visible commit must touch `CHANGELOG.md`** under the `## [Unreleased]` section, in the appropriate subsection: + +- **Added** — new features or capabilities. +- **Changed** — changes to existing functionality. +- **Deprecated** — soon-to-be-removed features. +- **Removed** — now-removed features. +- **Fixed** — bug fixes. +- **Security** — vulnerability fixes. + +Entries should be short imperative phrases that describe user-facing impact — not implementation detail. "Added sidecar PTY support for terminal pane" beats "Added `internal/pty/session.go`." + +**What skips the changelog:** pure bookkeeping commits that have no user-visible effect (typo fix in internal comment, `.gitignore` tweak, lint config change, reformatting). When in doubt, add an entry — the harm of an extra line is zero. + +When a commit spans multiple entries (e.g. a feature that adds one thing and fixes another), add a line under each applicable subsection rather than cramming both into one. + +## Cutting a release + +Cutting a release is its own commit. In a single commit: + +1. Move all entries from `## [Unreleased]` under a new heading `## [X.Y.Z] — YYYY-MM-DD`. +2. Leave an empty `## [Unreleased]` section at the top with its subsection skeleton ready. +3. Bump `project.yaml` `version:` to `X.Y.Z` (drop the `-dev` suffix for the tag; re-add it on the next development commit if desired). +4. Commit subject: `release vX.Y.Z`. + +`project.yaml` is the single source of truth for the version — the Makefile reads it for ldflag stamping of the sidecar binary, and the Flutter app reads it for build info. Bumping `project.yaml` and the changelog out of sync is the mistake this rule prevents. + +## Attribution trailer + +Every commit ends with the Claude co-author line: + +``` +Co-Authored-By: Claude +``` + +The model-identifier variant produced by the Claude Code harness (e.g. `Co-Authored-By: Claude Opus 4.7 (1M context) `) is also accepted — don't rewrite it if the harness emits that form. + +## HEREDOC discipline + +Pass commit messages via HEREDOC so multi-line formatting survives: + +```bash +git commit -m "$(cat <<'EOF' +short imperative summary + +Optional longer body explaining why this change was needed, +wrapped at about 72 characters. + +Co-Authored-By: Claude +EOF +)" +``` + +Never pass multi-line messages via `-m "line1\nline2"` or multiple `-m` flags — Git's behavior differs between shells and quoting regimes and the trailer can end up in the wrong place. + +## What not to commit + +- `.env` and any `*.env.local` — see `.gitignore`. +- `.claude/settings.local.json` — user-specific Claude Code settings, ignored. +- Build artefacts: `sidecar/bin/`, `sidecar/dist/`, `build/` (Flutter output), `app/.dart_tool/` — gitignored. +- SQLite index files (`*.sqlite`, `*.sqlite-wal`, `*.sqlite-shm`, `*.db`) — caches generated against local repos; must never land here. Gitignored defensively. +- Coverage / test output (`*.out`, `coverage.*`, `*.test`) — gitignored. + +## Safety reminders (reinforced from the global Claude Code protocol) + +- **Never** `--no-verify`. If a pre-commit hook fails, fix the underlying issue and create a new commit. +- **Never** `--amend` a commit unless the user explicitly asks. A failed-hook commit didn't land, so amending would overwrite the *previous* commit and lose work. +- **Never** force-push to `main` or `master`. Warn the user if they ask. +- When staging, prefer naming specific files over `git add -A` / `git add .` — those can sweep in secrets or unintended files. +- `git status` before staging, `git diff --staged` before committing, `git log -1` after committing to confirm. diff --git a/.claude/skills/skill-create/SKILL.md b/.claude/skills/skill-create/SKILL.md new file mode 100644 index 00000000..623dd0c7 --- /dev/null +++ b/.claude/skills/skill-create/SKILL.md @@ -0,0 +1,203 @@ +--- +name: skill-create +description: > + Guidance for creating effective Claude Code skills (.skill packages). + Use when the user wants to create, build, design, or iterate on a skill — + including writing SKILL.md files, bundling scripts/references/assets, + initializing new skills, packaging skills, or improving existing ones. + Triggers on requests like "create a skill", "make a new skill", + "build a skill for X", "package this skill", or "improve my skill". +--- + + +# Skill Creator + +## About Skills + +Skills are modular, self-contained packages that extend Claude's capabilities +by providing specialized knowledge, workflows, and tools. They transform Claude +from a general-purpose agent into a specialized agent equipped with procedural +knowledge that no model can fully possess. + +### What Skills Provide + +- **Specialized workflows** — Multi-step procedures for specific domains +- **Tool integrations** — Instructions for working with specific file formats or APIs +- **Domain expertise** — Company-specific knowledge, schemas, business logic +- **Bundled resources** — Scripts, references, and assets for complex and repetitive tasks + +## Core Principles + +### Concise is Key + +The context window is a public good. Skills share it with everything else Claude +needs: system prompt, conversation history, other skills' metadata, and the +actual user request. + +Default assumption: Claude is already very smart. Only add context Claude doesn't +already have. Challenge each piece of information: "Does Claude really need this +explanation?" and "Does this paragraph justify its token cost?" + +Prefer concise examples over verbose explanations. + +### Set Appropriate Degrees of Freedom + +Match specificity to the task's fragility and variability: + +- **High freedom** (text-based instructions): Multiple approaches valid, decisions + depend on context, heuristics guide the approach. +- **Medium freedom** (pseudocode or scripts with parameters): Preferred pattern + exists, some variation acceptable, configuration affects behavior. +- **Low freedom** (specific scripts, few parameters): Operations are fragile and + error-prone, consistency is critical, specific sequence must be followed. + +Think of Claude as exploring a path: a narrow bridge with cliffs needs specific +guardrails (low freedom), while an open field allows many routes (high freedom). + +## Anatomy of a Skill + +``` +skill-name/ +├── SKILL.md (required) +│ ├── YAML frontmatter metadata (required) +│ │ ├── name: (required) +│ │ ├── description: (required) +│ │ └── compatibility: (optional, rarely needed) +│ └── Markdown instructions (required) +└── Bundled Resources (optional) + ├── scripts/ - Executable code (Python/Bash/etc.) + ├── references/ - Documentation loaded into context as needed + └── assets/ - Files used in output (templates, icons, fonts, etc.) +``` + +### SKILL.md (required) + +- **Frontmatter (YAML)**: `name` and `description` fields (required). Only these + are read by Claude to determine when the skill triggers — be clear and + comprehensive. The `compatibility` field is for environment requirements but + most skills don't need it. +- **Body (Markdown)**: Instructions and guidance. Only loaded AFTER the skill + triggers. + +### Bundled Resources (optional) + +**Scripts (`scripts/`)** — Executable code for tasks requiring deterministic +reliability or that are repeatedly rewritten. + +**References (`references/`)** — Documentation loaded as needed into context. +Keep SKILL.md lean; move detailed reference material, schemas, and examples here. +If files are large (>10k words), include grep search patterns in SKILL.md. + +**Assets (`assets/`)** — Files used in output, not loaded into context (templates, +images, icons, boilerplate code, fonts). + +### What to NOT Include + +Do NOT create extraneous files like README.md, INSTALLATION_GUIDE.md, +QUICK_REFERENCE.md, CHANGELOG.md, etc. The skill should only contain information +needed for an AI agent to do the job. + +## Progressive Disclosure + +Skills use a three-level loading system: + +1. **Metadata** (name + description) — Always in context (~100 words) +2. **SKILL.md body** — When skill triggers (<5k words) +3. **Bundled resources** — As needed (unlimited; scripts can run without reading) + +Keep SKILL.md body under 500 lines. Split content into separate files when +approaching this limit. Reference split files from SKILL.md with clear +descriptions of when to read them. + +### Disclosure Patterns + +**Pattern 1: High-level guide with references** — Keep overview in SKILL.md, +link to detail files loaded only when needed. + +**Pattern 2: Domain-specific organization** — Organize content by domain +(e.g., `references/finance.md`, `references/sales.md`) so only relevant content +is loaded. + +**Pattern 3: Conditional details** — Show basic content, link to advanced +content loaded only when the user needs those features. + +Guidelines: +- Avoid deeply nested references — keep one level deep from SKILL.md +- Structure longer reference files with a table of contents at the top + +## Skill Creation Process + +Follow these steps in order, skipping only with clear reason: + +### Step 1: Understand the Skill with Concrete Examples + +Skip only when usage patterns are already clearly understood. + +Ask the user for concrete examples of how the skill will be used: +- "What functionality should the skill support?" +- "Can you give some examples of how this skill would be used?" +- "What would a user say that should trigger this skill?" + +Avoid overwhelming users — start with the most important questions. + +### Step 2: Plan the Reusable Skill Contents + +Analyze each example by considering how to execute from scratch and identifying +what scripts, references, and assets would help with repeated execution. + +Establish a list of reusable resources: scripts, references, and assets. + +### Step 3: Initialize the Skill + +Create the skill directory manually: + +``` +mkdir -p / +``` + +Then create `SKILL.md` with frontmatter and body. Add `scripts/`, `references/`, +and `assets/` subdirectories only as needed. + +Skip if iterating on an existing skill. + +### Step 4: Edit the Skill + +Remember the skill is for another Claude instance to use. Include beneficial, +non-obvious information. + +For design patterns, consult: +- `references/workflows.md` — Sequential workflows and conditional logic +- `references/output-patterns.md` — Template and example patterns + +**Implementation order:** +1. Start with reusable resources (`scripts/`, `references/`, `assets/`) +2. Test added scripts by running them +3. Delete unused example files from initialization +4. Update SKILL.md + +**Writing guidelines:** Always use imperative/infinitive form. + +**Frontmatter:** +- `name`: The skill name — use **domain-action** naming: `{domain}-{action}`. + The domain is the system/area the skill operates on, the action is what it does. + Examples: `pr-review`, `sprint-plan`, `docs-search`, `git-commit`, `debt-scan`. + Multi-action wrappers (like `ticket`) can use the domain name alone. + The directory name must match the `name` field. +- `description`: Primary triggering mechanism. Include what the skill does AND + specific triggers/contexts. All "when to use" info goes here (not in body). + +**Body:** Instructions for using the skill and its bundled resources. + +### Step 5: Validate the Skill + +Check the skill manually: +- Frontmatter has `name` and `description` +- SKILL.md body is under 500 lines +- No extraneous files (README.md, CHANGELOG.md, etc.) +- Scripts are executable and tested +- References are referenced from SKILL.md + +### Step 6: Iterate + +After real usage, notice struggles or inefficiencies, identify needed updates, +implement changes, and test again. diff --git a/.gitignore b/.gitignore index 44af8b2b..8a5f649f 100644 --- a/.gitignore +++ b/.gitignore @@ -184,5 +184,5 @@ logs/ # Credentials *-credentials.md -# Claude Code -.claude/ +# Claude Code — user-specific settings only; project-level settings and skills are committed +.claude/settings.local.json diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..3f1d967a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,33 @@ +# Changelog + +All notable changes to clide are documented in this file. + +The format follows [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +This changelog tracks the Flutter rebuild at the repo root. The Python +Textual implementation's changelog is preserved under +[`legacy/CHANGELOG.md`](legacy/CHANGELOG.md). + +Versions are tracked in [`project.yaml`](project.yaml) under `version:`, +which is the single source of truth. Cutting a release means (a) moving +the entries below from `## [Unreleased]` under a new dated version +heading, and (b) bumping `project.yaml` `version:` in the same commit. + +## [Unreleased] + +### Added + +- Architectural decision records carried forward from the short-lived + `claudian` plugin project (discarded in favour of this Flutter + rebuild): + [ADR 0001](docs/ADRs/0001-cli-first-not-mcp.md) — CLI-first, not MCP. + [ADR 0002](docs/ADRs/0002-sidecar-language-go.md) — Sidecar language: Go. + [ADR 0003](docs/ADRs/0003-pql-as-supporter-tool.md) — pql as supporter tool; wrap, don't duplicate; pql is a Clide subsystem when present. + [ADR 0004](docs/ADRs/0004-ignore-file-strategy.md) — Ignore file strategy (`ignore_files:` in `.pql/config.yaml`, layered). +- Claude Code configuration under `.claude/`: project-level + allow/deny permissions and two skills — `skill-create` (generic + skill authoring guidance) and `git-commit` (this repo's commit + conventions: no Conventional Commits, Keep a Changelog discipline, + `project.yaml`-and-changelog-bumped-together rule, attribution + trailer, safety reminders). diff --git a/docs/ADRs/0001-cli-first-not-mcp.md b/docs/ADRs/0001-cli-first-not-mcp.md new file mode 100644 index 00000000..15b39300 --- /dev/null +++ b/docs/ADRs/0001-cli-first-not-mcp.md @@ -0,0 +1,34 @@ +# ADR 0001 — CLI-first, not MCP + +**Status:** accepted +**Date:** 2026-04-20 (ported from the claudian lineage) + +## Context + +Clide exposes capabilities to Claude Code (panes, terminals, git, +pql queries, canvas, graph). The two mainstream options for that +interface are: + +1. A Model Context Protocol (MCP) server the agent connects to. +2. A plain Bash CLI the agent calls from its shell, matching the + contract `pql` already follows. + +## Decision + +Claude talks to Clide exclusively via Bash (`clide ...`). No MCP +server. No protocol layer in Claude's face. The CLI uses the same +exit-code + stderr-JSON contract as pql. + +## Consequences + +- Same mental model as pql for the agent — one tool-use pattern + covers both. +- No MCP runtime to host, authenticate, or keep in sync with client + versions. +- User/Claude parity is easier to enforce: every CLI subcommand must + have a UI affordance in the Flutter app and vice versa. +- Claude Code's `Bash(clide *)` allow rule is the only configuration + Clide needs on the agent side. +- If an MCP-only integration becomes compelling later (e.g. a + multi-agent scenario), nothing here precludes adding one that + shells out to the same CLI. diff --git a/docs/ADRs/0002-sidecar-language-go.md b/docs/ADRs/0002-sidecar-language-go.md new file mode 100644 index 00000000..d1b698b6 --- /dev/null +++ b/docs/ADRs/0002-sidecar-language-go.md @@ -0,0 +1,44 @@ +# ADR 0002 — Sidecar language: Go + +**Status:** accepted +**Date:** 2026-04-20 (ported from the claudian lineage) + +## Context + +The Clide sidecar owns PTYs, subprocesses, file watchers, git +shelling-out, and the IPC server. It ships as a single static binary +that also serves as the `clide` CLI in one-shot mode. The Flutter +desktop app talks to it over IPC; Claude talks to it via the CLI. +Language candidates were Go and Rust. + +Related hard constraint: **no heavy lifting in the UI layer.** The +Flutter app stays focused on rendering and interaction. Everything +heavy (PTYs, subprocesses, file watching, git, pql invocations) +lives in the sidecar. Reason: keep the UI layer thin and the +security-sensitive surface auditable in one language. + +## Decision + +The sidecar/CLI is written in Go. + +Rationale: + +- **Matches pql.** pql is Go; Clide wraps pql and reaches into its + idioms constantly. Shared toolchain and shared patterns cut + cognitive overhead. +- **Static binary.** Single artifact, trivial cross-compile, no + runtime dependencies on the user's machine. +- **PTY story is fine.** `creack/pty` covers what we need; Rust's + crates are marginally nicer but not decisive. +- **Muscle memory.** Build pipeline, `project.yaml` conventions, + goreleaser setup, exit-code contract, diagnostic format — all + already established in pql and portable one-to-one. + +## Consequences + +- Module path: `git.schweitz.net/jpmschweitzer/clide/sidecar`. +- Layout mirrors pql: `cmd/clide/main.go`, `internal/cli`, + `internal/version` (ldflag-stamped `Version`, `Commit`, `Date`), + `internal/diag` (exit codes + stderr-JSON diagnostics). +- Same Makefile shape: version read from `project.yaml` via awk, + stamped via `-ldflags -X`. diff --git a/docs/ADRs/0003-pql-as-supporter-tool.md b/docs/ADRs/0003-pql-as-supporter-tool.md new file mode 100644 index 00000000..801841bc --- /dev/null +++ b/docs/ADRs/0003-pql-as-supporter-tool.md @@ -0,0 +1,61 @@ +# ADR 0003 — pql as supporter tool; Clide wraps, never duplicates + +**Status:** accepted +**Date:** 2026-04-20 (ported from the claudian lineage) + +## Context + +[`pql`](https://github.com/postmeridiem/pql) is a pre-existing Go +CLI that indexes a markdown-bearing directory tree into SQLite and +exposes its semantics (frontmatter, wikilinks, tags, headings, +bases) through a query surface. Clide needs those capabilities for +its Query panel, canvas drivers, graph view, and any feature that +needs to know structure. + +## Decision + +Two complementary rules. + +### 1. Wrap, don't duplicate. + +Clide never re-implements backlinks, ranking, frontmatter parsing, +or wikilink resolution for query purposes. If a capability is +missing in pql, it is added upstream in pql's repo and Clide bumps +the dependency. + +The only place Clide contains pql logic is +`sidecar/internal/pql/` — pure shell-outs to the `pql` binary, no +logic beyond invocation and result rendering. + +### 2. pql is a Clide subsystem when Clide is present in the repo. + +Broader than "wrap, don't duplicate." When Clide is loaded in a +repo, it owns pql's lifecycle and the config keys it cares about. +On load, Clide writes its current state into `.pql/config.yaml` — +no conditional sync, no "did anything change" logic. + +Clide only stomps the keys it manages (starting with `ignore_files:` +— see ADR 0004). Other pql config keys are left alone so pql's +config surface can grow independently. + +Clide does **not** touch pql's index/cache data under `/.pql/` +— that stays pql's private store. Only the config file is Clide's +to edit. + +In repos without Clide, pql works standalone, unaffected. The rule: +direct-pql users get vanilla pql; Clide users get pql managed by +Clide. + +## Consequences + +- One source of truth for markdown semantics (pql). +- Clide's `sidecar/internal/pql/` package is deliberately thin. +- Any new query capability the UI wants goes through a pql upstream + PR, not a local workaround. +- User never has to learn pql's config file to get consistent + behavior — Clide manages it. +- The arrow Clide → pql is never inverted: pql stays ignorant of + its wrapper, never hardcodes Clide filenames. +- pql is also the **only** query engine. Obsidian-style inline + "bases" (YAML query tables embedded in markdown) are explicitly + not supported; queries live at the repo level where they belong. diff --git a/docs/ADRs/0004-ignore-file-strategy.md b/docs/ADRs/0004-ignore-file-strategy.md new file mode 100644 index 00000000..a1a1525d --- /dev/null +++ b/docs/ADRs/0004-ignore-file-strategy.md @@ -0,0 +1,73 @@ +# ADR 0004 — Ignore file strategy + +**Status:** accepted +**Date:** 2026-04-20 (ported from the claudian lineage) + +## Context + +Clide's working assumption is that the git repo *is* the workspace +— no separate "vault" concept layered on top. Every file-enumerating +surface in Clide (pql query panels, canvas drivers, graph view, +sidecar file watchers, pane lists, file tree) needs to skip the +obvious junk — `vendor/`, `node_modules/`, `dist/`, build artifacts +— or results drown in noise. + +## Decision + +One mechanism everywhere: the `ignore_files:` list in +`.pql/config.yaml`. An ordered list of gitignore-shaped files, later +entries win on per-pattern conflicts. + +### Default + +pql defaults to `ignore_files: [.gitignore]`. Most repos already +keep exclusions there, so zero config in a code repo; in a +notes-only directory `.gitignore` doesn't exist and the default is +a safe no-op. + +### Clide sync + +Per ADR 0003's "pql is a Clide subsystem when present" rule, Clide +writes the list on load: + +- If `.clideignore` exists in the repo: + `ignore_files: [.gitignore, .clideignore]`. Clide-specific deltas + (including `!pattern` negations) layer on top of gitignore. +- Otherwise: `ignore_files: [.gitignore]` (matches the pql default). + +No conditional sync. Clide only stomps `ignore_files:`; other pql +config keys are left alone. + +### `.clideignore` semantics + +- Carries **only** the Clide-specific deviations from `.gitignore`. + Never duplicate gitignore's contents. +- Supports `!pattern` negations to un-ignore specific entries (e.g. + `!.github/` to expose workflow docs in query results). + +### Walker magic: none except `.git/` + +Git self-hides `.git/` — that's the only invisible exclusion in the +stack. Every other tool is explicit: pql adds `.pql/` to +`.gitignore` at install time, and Clide adds any private dirs it +introduces (e.g. `.clide/`) to `.gitignore` on install. Exclusion +flows through the normal `ignore_files:` chain; no hardcoded walker +exceptions for tool-owned dirs. + +### Same list, same rules, everywhere + +Sidecar consumers (watchers, canvas, pane list, file tree, graph +view) read the same key from `.pql/config.yaml` and apply identical +precedence, so Claude and the user always see the same filtered +surface. + +## Consequences + +- Users get one config knob, in a file they might already know (pql + users) or never need to touch (Clide-only users). +- `.clideignore` is short by design — it's deltas, not a full list. +- Removing Clide from a repo leaves pql working with vanilla + defaults (Clide's last-written `ignore_files:` stays until pql or + the user rewrites it; worth reconsidering during uninstall design). +- Upstream pql work: the `ignore_files:` list is already the shape + pql has landed on (plural, ordered, defaults to `[.gitignore]`).