carry forward ADRs, Claude Code config, and changelog discipline
Ports the patterns that crystallized during the short-lived claudian plugin project (discarded in favour of this Flutter rebuild): - ADRs 0001-0004 capture decisions that survive the host change — CLI-first over MCP, Go for the sidecar, pql as a supporter tool that becomes a clide-managed subsystem when present, and the ignore-file strategy that wires all file-enumerating surfaces through one knob in .pql/config.yaml. - .claude/settings.json and the git-commit and skill-create skills come over with naming updated for clide. The git-commit skill's "no Conventional Commits" convention supersedes the Python-era clide style under legacy/; the Keep-a-Changelog discipline and the project.yaml-version-and-changelog-bumped-together rule apply going forward. - CHANGELOG.md starts fresh at the repo root to track the Flutter rebuild. The Python changelog is preserved under legacy/. .gitignore narrows from `.claude/` to just `.claude/settings.local.json` so project-level config and skills travel with the repo. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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 *)"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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 <specific paths>`** — 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 <noreply@anthropic.com>
|
||||
```
|
||||
|
||||
The model-identifier variant produced by the Claude Code harness (e.g. `Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>`) 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 <noreply@anthropic.com>
|
||||
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.
|
||||
@@ -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 <output-directory>/<skill-name>
|
||||
```
|
||||
|
||||
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.
|
||||
+2
-2
@@ -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
|
||||
|
||||
@@ -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).
|
||||
@@ -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.
|
||||
@@ -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`.
|
||||
@@ -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 `<repo>/.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.
|
||||
@@ -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]`).
|
||||
Reference in New Issue
Block a user