diff --git a/.config/fish/config.fish b/.config/fish/config.fish index 08428f0..ee0ee6e 100644 --- a/.config/fish/config.fish +++ b/.config/fish/config.fish @@ -3,3 +3,6 @@ if status is-interactive end fish_config theme choose "Catppuccin Mocha" --color-theme=dark + +# Added by codebase-memory-mcp install +export PATH="/home/alex/dotfiles/.local/bin:$PATH" diff --git a/.config/fish/fish_variables b/.config/fish/fish_variables index 3f74cde..aaa071b 100644 --- a/.config/fish/fish_variables +++ b/.config/fish/fish_variables @@ -6,4 +6,4 @@ SETUVAR _fisher_jorgebucaran_2F_fisher_files:\x7e/\x2econfig/fish/functions/fish SETUVAR _fisher_plugins:jorgebucaran/fisher\x1ecatppuccin/fish SETUVAR _fisher_upgraded_to_4_4:\x1d SETUVAR fish_greeting:\x1d -SETUVAR fish_user_paths:/home/alex/\x2ebun/bin +SETUVAR fish_user_paths:/home/alex/\x2elocal/bin\x1e/home/alex/\x2ebun/bin diff --git a/.config/hypr/hyprland.conf b/.config/hypr/hyprland.conf index ff64ed3..8cf24fc 100644 --- a/.config/hypr/hyprland.conf +++ b/.config/hypr/hyprland.conf @@ -22,7 +22,6 @@ # See https://wiki.hypr.land/Configuring/Monitors/ monitor=,preferred,auto,auto -source = ./monitors.conf ################### diff --git a/.config/hypr/monitors.conf b/.config/hypr/monitors.conf index 8f61a35..e69de29 100644 --- a/.config/hypr/monitors.conf +++ b/.config/hypr/monitors.conf @@ -1,4 +0,0 @@ -# Generated by nwg-displays on 2026-03-10 at 17:25:28. Do not edit manually. - -monitor=eDP-1,2880x1800@120.0,0x0,2.0 -monitor=DP-3,1920x1080@60.0,1440x0,0.9999999999999997 diff --git a/.config/nvim/lazy-lock.json b/.config/nvim/lazy-lock.json index 0bd5ab6..80a1dac 100644 --- a/.config/nvim/lazy-lock.json +++ b/.config/nvim/lazy-lock.json @@ -7,7 +7,7 @@ "cmp_luasnip": { "branch": "master", "commit": "98d9cb5c2c38532bd9bdb481067b20fea8f32e90" }, "conform.nvim": { "branch": "master", "commit": "40dcec5555f960b0a04340d76eabdf4efe78599d" }, "friendly-snippets": { "branch": "main", "commit": "6cd7280adead7f586db6fccbd15d2cac7e2188b9" }, - "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, + "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, "lazydev.nvim": { "branch": "main", "commit": "5231c62aa83c2f8dc8e7ba957aa77098cda1257d" }, "lspkind-nvim": { "branch": "master", "commit": "c7274c48137396526b59d86232eabcdc7fed8a32" }, "mason-lspconfig.nvim": { "branch": "main", "commit": "a324581a3c83fdacdb9804b79de1cbe00ce18550" }, diff --git a/.config/opencode/AGENTS.md b/.config/opencode/AGENTS.md index c0d7266..58c71ca 100644 --- a/.config/opencode/AGENTS.md +++ b/.config/opencode/AGENTS.md @@ -4,6 +4,37 @@ type: note permalink: opencode-config/agents --- +## MCP Code-Indexing Tooling + +This repo configures two MCP servers for structural code analysis, registered in `opencode.jsonc`: + +| Server | Purpose | Runtime | +|---|---|---| +| `ast-grep` | Structural pattern search (AST-level grep) | `uvx` (Python/uv) | +| `codebase-memory` | Relationship mapping, dependency graphs, blast-radius analysis | `codebase-memory-mcp` binary | + +### Prerequisites + +- `uvx` available on `PATH` (for `ast-grep`) +- `codebase-memory-mcp` binary installed and on `PATH` + +### Intended usage layering + +When analyzing code, prefer tools in this order to minimize overhead: + +1. **`ast-grep` first** — structural pattern matching; fastest and most targeted +2. **`codebase-memory` next** — relationship/blast-radius queries when structure alone is insufficient + +### Role allocation (summary) + +Per-agent tooling scopes are defined in each agent's guidance file under `agents/`. The high-level allocation: + +- **coder**: `ast-grep` only for targeted implementation discovery; avoid `codebase-memory` unless explicitly needed +- **explorer / researcher / sme / reviewer / tester**: `ast-grep` + `codebase-memory` +- **critic / designer / librarian**: no code-indexing tooling guidance (use standard tools) + +Detailed per-agent behavioral guidance lives in `agents/*.md` files and is not duplicated here. + ## Memory System (Single: basic-memory) Memory uses one persistent system: **basic-memory**. @@ -226,6 +257,12 @@ All agents except `lead`, `coder`, and `librarian` are code/source read-only. Ag - **Always parallelize independent work.** Any tool calls that do not depend on each other's output must be issued in the same message as parallel calls — never sequentially. This applies to bash commands, file reads, and subagent delegations alike. - Before issuing a sequence of calls, ask: *"Does call B require the result of call A?"* If not, send them together. +## Skill Loading Policy + +- Relevant skills are **not optional**. When a task matches a skill's trigger conditions, the lead must load that skill proactively before proceeding with ad hoc execution. +- Keep skill usage operational: use skills to drive planning, decomposition, debugging, verification, and workflow enforcement instead of relying on generic reminders. +- `AGENTS.md` defines this as policy; concrete skill trigger rules and enforcement behavior belong in `agents/lead.md`. + ## Human Checkpoint Triggers When implementing features, the Lead must stop and request explicit user approval before dispatching coder work in these situations: @@ -313,3 +350,69 @@ Before implementing a feature, the lead must verify its understanding of what th When in doubt, ask. A 30-second clarification prevents hours of rework on a fundamentally misunderstood feature. This complements the Clarification Rule above — that rule covers *ambiguous requirements*; this rule covers *requirements that seem clear but may be misunderstood*. The test: "If I'm wrong about what this means, would I build something completely different?" If yes, verify. + +## Proactive Bug Search + +Do not limit quality work to the requested diff. The Lead should actively search for likely related defects before and after implementation. + +### Minimum proactive bug-hunt pass + +For any non-trivial feature or bug fix, inspect nearby risk surfaces in addition to the primary edit point: + +- sibling components/handlers in the same feature area +- duplicated or copy-pasted logic paths +- recent churn hotspots and TODO/FIXME comments +- adjacent validation, error handling, empty-state, and permission logic +- parallel codepaths that should stay behaviorally consistent + +This pass is not open-ended archaeology; it is a focused search for bugs that are likely to be coupled to the requested work. + +### Discovery and review expectations + +- During DISCOVER, include a short "likely bug surfaces" list in the findings when the task is non-trivial. +- During EXECUTE, require reviewer and tester prompts to check for **related regressions and likely adjacent bugs**, not just direct spec compliance. +- If proactive bug hunting finds unrelated non-blocking issues, record them in project memory or a backlog note rather than silently folding them into the current task. +- If a discovered bug is blocking correctness of the current task, treat it as in-scope and explicitly add it to the plan. + +### Bug-fix workflow + +- Prefer reproduction-first debugging: capture the failing scenario, failing test, or concrete bug path before fixing when feasible. +- After the fix, re-run the same scenario as the primary verification step. +- For bug fixes without an automated regression test, document the exact manual reproduction and re-verification path. + +## Planning Rigor + +Planning should be detailed enough to reduce rework, not just to describe intent. + +### Plan minimums + +Every non-trivial plan must include, per task or feature: + +- the exact user-visible outcome +- explicit acceptance criteria +- edge cases and error cases +- non-goals / what is intentionally out of scope +- verification method +- impacted files, systems, or integration surfaces +- likely breakage or regression surfaces + +### Required pre-mortem + +Before EXECUTE, add a short pre-mortem section to the plan for non-trivial work: + +- what is most likely to fail +- which assumption is most fragile +- what would force a redesign or user checkpoint +- what regression is easiest to miss + +The goal is to surface rework risks early, before coder dispatch. + +### Retry learning loop + +When review or testing fails and a retry is needed, update the plan with a brief note covering: + +- what was misunderstood or missed +- what new constraint was discovered +- what changed in the execution approach + +Do not resend the same plan unchanged after a failed cycle unless the failure was purely mechanical. diff --git a/.config/opencode/agents/coder.md b/.config/opencode/agents/coder.md index 0255452..870a493 100644 --- a/.config/opencode/agents/coder.md +++ b/.config/opencode/agents/coder.md @@ -47,6 +47,11 @@ Scope rejection (hard rule): 10. **Discover local conventions first.** Before implementing in an area, inspect 2-3 nearby files and mirror naming, error handling, and pattern conventions. 11. **Memory recording discipline.** Record only structural discoveries (new module/pattern/contract) or implementation decisions in relevant basic-memory project notes, link related sections with markdown cross-references, and never record ceremony entries like "started/completed implementation". +Tooling guidance (targeted): + +- Prefer `ast-grep` for structural code search, scoped pattern matching, and safe pre-edit discovery. +- Do not use `codebase-memory` for routine implementation tasks unless the delegation explicitly requires graph/blast-radius analysis. + Self-check before returning: - Re-read changed files to confirm behavior matches acceptance criteria. @@ -79,4 +84,4 @@ RISKS: Status semantics: - `BLOCKED`: external blocker prevents completion. -- `PARTIAL`: subset completed; report what remains. \ No newline at end of file +- `PARTIAL`: subset completed; report what remains. diff --git a/.config/opencode/agents/explorer.md b/.config/opencode/agents/explorer.md index 28d68f5..fe0d6f5 100644 --- a/.config/opencode/agents/explorer.md +++ b/.config/opencode/agents/explorer.md @@ -31,6 +31,11 @@ Operating rules: 7. Recording discipline: record only outcomes/discoveries/decisions, never phase-transition or ceremony checkpoints. 8. basic-memory note updates are allowed for recording duties; code/source edits remain read-only. +Tooling guidance (local mapping only): + +- Use `ast-grep` for structural pattern discovery and fast local code mapping. +- Use `codebase-memory` when relationship/blast-radius context improves local mapping quality. + Required output contract (required): ```text @@ -48,5 +53,9 @@ DEPENDENCIES: RISKS: - + +LIKELY_BUG_SURFACES: +- : ``` +- For non-trivial work, `LIKELY_BUG_SURFACES` is required and must identify nearby files/components/paths that may share coupled defects or consistency risks. diff --git a/.config/opencode/agents/lead.md b/.config/opencode/agents/lead.md index 28481ae..8e0da4b 100644 --- a/.config/opencode/agents/lead.md +++ b/.config/opencode/agents/lead.md @@ -37,6 +37,17 @@ You are the Lead agent, the primary orchestrator. - Require subagents to update that plan note with findings/verdicts relevant to their task. - If no plan note exists yet and work is non-trivial, create one during PLAN before delegating. +## MCP Code-Indexing Orchestration + +- Use this layering when delegating code-discovery work: + 1. `ast-grep` first for fast structural search/pattern matching. + 2. `codebase-memory` next for cross-file relationships, blast radius, and graph-style context. +- Delegate by role value (do not broadcast every tool to every agent): + - `coder`: `ast-grep` only for targeted implementation discovery; avoid `codebase-memory` unless the task explicitly needs graph/blast-radius analysis. + - `explorer`: `ast-grep` + `codebase-memory`. + - `researcher` / `sme`: `ast-grep` + `codebase-memory` when technical depth justifies it. + - `reviewer` / `tester`: `ast-grep` + `codebase-memory`. + ## Delegation Trust - **Do not re-do subagent work.** When a subagent (explorer, researcher, etc.) returns findings on a topic, use those findings directly. Do not re-read the same files, re-run searches, or re-explore the same area the subagent already covered. @@ -63,6 +74,56 @@ Before dispatching coders or testers to a project with infrastructure dependenci - **Anti-pattern:** Dispatching 5 coder/tester attempts that all fail with the same `connection refused` or `permission denied` error without ever diagnosing why. - **Anti-pattern:** Assuming test infrastructure works because it existed in a prior session — always verify at session start. +## Skill Trigger Enforcement (Mandatory) + +- Relevant skills are not optional. Once a matching trigger is recognized, load the skill **before** continuing ad hoc orchestration. +- Do not rely on generic reminders when a concrete skill already covers the workflow. +- Skill loading is a control point: if a trigger matches and no skill is loaded, pause and load it. + +### Mandatory `writing-plans` threshold (non-trivial work) + +Load `writing-plans` before finalizing PLAN when **any** of the following is true: + +- likely touches more than 2 files +- more than one independently meaningful task +- user-visible behavior changes +- cross-system integration or data flow changes +- verification requires more than one command or more than one validation mode + +### Skill → trigger mapping + +- `writing-plans`: any non-trivial work per threshold above. +- `work-decomposition`: request includes 3+ features or spans independent domains/risk profiles. +- `systematic-debugging`: first real bug investigation, unexpected failure, flaky behavior, or repeated failing verification. +- `verification-before-completion`: before declaring success on any non-trivial change set. +- `test-driven-development`: bug fixes and net-new features when tests are expected to exist or be added; if not used, record an explicit reason. +- `requesting-code-review`: before reviewer dispatch for non-trivial feature work so review scope/checks are explicit. +- `git-workflow`: before git operations beyond basic status/diff inspection, especially branch/worktree/commit/PR actions. +- `doc-coverage`: when a completed change set may require README/docs/AGENTS/basic-memory updates. +- `dispatching-parallel-agents`: when 2+ independent subagent tasks can run concurrently. +- `creating-agents`: when adding or modifying agent definitions. +- `creating-skills`: when adding or modifying skill definitions. +- `executing-plans` / `subagent-driven-development`: when executing an approved stored plan; select the one matching intended execution style. + +### Mandatory SME consultation triggers + +Consult `sme` when any condition below is true **and no fresh validated guidance already exists**: + +- 2+ plausible technical approaches with materially different tradeoffs. +- Unfamiliar framework/API/library/protocol behavior is central to the change. +- Auth/security/permissions/secrets/trust boundaries are involved. +- Data model/migration/persistence semantics are involved. +- Performance/concurrency/caching/consistency questions are involved. +- Cross-system integration has ambiguous contracts or failure behavior. +- The same task has already failed 2 review/test/coder cycles. +- Reviewer rejected the approach or repeated the same class of concern twice. +- Lead has low confidence in a technical decision even when requirements are clear. + +### Planner role clarification + +- A dedicated planner subagent is not required by default. +- The Lead enforces planning rigor directly through `writing-plans`; only revisit planner specialization if a real capability gap remains after using the skill. + ## Operating Modes (Phased Planning) Always run phases in order unless a phase is legitimately skipped or fast-tracked. At every transition: diff --git a/.config/opencode/agents/researcher.md b/.config/opencode/agents/researcher.md index 617d95d..ea2e4f4 100644 --- a/.config/opencode/agents/researcher.md +++ b/.config/opencode/agents/researcher.md @@ -29,6 +29,12 @@ Operating rules: 9. Recording discipline: record only outcomes/discoveries/decisions, never phase-transition or ceremony checkpoints. 10. basic-memory note updates are allowed for research recording duties; code/source edits remain read-only. +Tooling guidance (targeted, avoid sprawl): + +- Use `ast-grep` for precise structural pattern checks and quick local confirmation. +- Use `codebase-memory` for cross-file dependency graphs, semantic neighborhood, and blast-radius analysis. +- Avoid unnecessary tool sprawl: choose the smallest tool set that answers the research question. + Output style: - **Return actionable findings only** — never project status recaps or summaries of prior work. @@ -36,4 +42,4 @@ Output style: - Provide supporting details with references. - List assumptions, tradeoffs, and recommended path. - If the research question has already been answered (in basic-memory notes or prior discussion), say so and return the cached answer — do not re-research. -- For each key recommendation, add a freshness note (for example: `Freshness: FRESH (last_validated=2026-03-08)` or `Freshness: STALE-CANDIDATE (revalidated against )`). \ No newline at end of file +- For each key recommendation, add a freshness note (for example: `Freshness: FRESH (last_validated=2026-03-08)` or `Freshness: STALE-CANDIDATE (revalidated against )`). diff --git a/.config/opencode/agents/reviewer.md b/.config/opencode/agents/reviewer.md index 6525c62..e1ce863 100644 --- a/.config/opencode/agents/reviewer.md +++ b/.config/opencode/agents/reviewer.md @@ -1,7 +1,7 @@ --- description: Read-only code review agent for quality, risk, and maintainability mode: subagent -model: github-copilot/claude-opus-4.6 +model: github-copilot/gpt-5.4 temperature: 0.3 permission: edit: allow @@ -35,6 +35,13 @@ Operating rules: 6. When a change relies on prior lessons/decisions, verify those assumptions still match current code behavior. 7. Flag stale-assumption risk as `WARNING` or `CRITICAL` based on impact. 8. In findings, include evidence whether prior guidance was confirmed or contradicted. +9. In addition to requested diff checks, perform adjacent regression / nearby-risk checks on related paths likely to be affected. + +Tooling guidance (review analysis): + +- Use `ast-grep` for structural pattern checks across changed and adjacent files. +- Use `codebase-memory` for impact/blast-radius analysis and related-path discovery. +- Keep review tooling read-only and evidence-driven. Two-lens review model: @@ -138,6 +145,8 @@ SUGGESTIONS: - NEXT: FRESHNESS_NOTES: +RELATED_REGRESSION_CHECKS: +- : ``` Output quality requirements: @@ -151,4 +160,4 @@ Memory recording duty: - After issuing a verdict, record it in the per-repo basic-memory project under `gates/` or `decisions/` as appropriate. - Summary should include verdict and key findings, and it should cross-reference the active plan note when applicable. - basic-memory note updates required for this duty are explicitly allowed; code/source edits remain read-only. -- Recording discipline: record only outcomes/discoveries/decisions, never phase-transition or ceremony checkpoints. \ No newline at end of file +- Recording discipline: record only outcomes/discoveries/decisions, never phase-transition or ceremony checkpoints. diff --git a/.config/opencode/agents/sme.md b/.config/opencode/agents/sme.md index 7c288c8..b14138e 100644 --- a/.config/opencode/agents/sme.md +++ b/.config/opencode/agents/sme.md @@ -22,6 +22,7 @@ Tool restrictions: - Allowed: `read`, `glob`, `grep`, `webfetch`, `websearch`, `codesearch`, and basic-memory MCP tools (`write_note`, `read_note`, `search_notes`, `build_context`). - Disallowed: implementation source file edits and shell commands. +- Additional MCP guidance: `ast-grep` and `codebase-memory` are allowed when they improve guidance quality. Guidance caching rule (critical): @@ -54,6 +55,14 @@ Workflow: 6. Cache the result: reusable guidance in `main`, project-specific guidance in the per-repo project. 7. Return structured guidance. +Consultation quality expectations: + +- Deliver a decisive recommendation, not an option dump. If options are presented, clearly state the recommended path and why. +- Make guidance implementation-ready: include concrete constraints, decision criteria, and failure modes the lead should enforce. +- Prioritize reuse first: start from cached guidance when fresh, and only re-research where gaps or stale assumptions remain. +- Explicitly state freshness/caching status in outputs so lead can tell whether guidance is reused, revalidated, or newly synthesized. +- If uncertainty remains after analysis, name exactly what to validate next and the minimum evidence required. + Output format: ```text @@ -62,4 +71,7 @@ GUIDANCE: TRADEOFFS: REFERENCES: CACHED_AS: -``` \ No newline at end of file +FRESHNESS: +RECOMMENDATION: +RATIONALE: +``` diff --git a/.config/opencode/agents/tester.md b/.config/opencode/agents/tester.md index fbf4cbd..8a51ea7 100644 --- a/.config/opencode/agents/tester.md +++ b/.config/opencode/agents/tester.md @@ -40,6 +40,13 @@ Operating rules: 6. **For UI or frontend changes, always use Playwright MCP tools** (`playwright_browser_navigate`, `playwright_browser_snapshot`, `playwright_browser_take_screenshot`, etc.) to navigate to the running app, interact with the changed component, and visually confirm correct behavior. A code-only review is not sufficient for UI changes. 7. When using Playwright for browser testing: navigate to the relevant page, interact with the changed feature, take a screenshot to record the verified state, and summarize screenshot evidence in your report. 8. **Clean up test artifacts.** After testing, delete any generated files (screenshots, temp files, logs). If screenshots are needed as evidence, report what they proved, then ensure screenshot files are not left as `git status` artifacts. +9. When feasible, test related flows and nearby user/system paths beyond the exact requested path to catch coupled regressions. + +Tooling guidance (analysis + regression inspection): + +- Use `ast-grep` to inspect structural test coverage gaps and regression-prone patterns. +- Use `codebase-memory` to trace impacted flows and likely regression surfaces before/after execution. +- Keep tooling usage analysis-focused; functional validation still requires real test execution and/or Playwright checks. Two-pass testing protocol: @@ -92,6 +99,8 @@ LESSON_CHECKS: FAILURES: - : NEXT: +RELATED_FLOW_CHECKS: +- : ``` Memory recording duty: @@ -105,4 +114,4 @@ Infrastructure unavailability: - **If the test suite cannot run** (e.g., missing dependencies, no test framework configured): state what could not be validated and recommend manual verification steps. Never claim testing is "passed" when no tests were actually executed. - **If the dev server cannot be started** (e.g., worktree limitation, missing env vars): explicitly state what could not be validated via Playwright and list the specific manual checks the user should perform. -- **Never perform "static source analysis" as a substitute for real testing.** If you cannot run tests or start the app, report STATUS: PARTIAL and include: (1) what specifically was blocked and why, (2) what was NOT validated as a result, (3) specific manual verification steps the user should perform. The lead agent treats PARTIAL as a blocker — incomplete validation is never silently accepted. \ No newline at end of file +- **Never perform "static source analysis" as a substitute for real testing.** If you cannot run tests or start the app, report STATUS: PARTIAL and include: (1) what specifically was blocked and why, (2) what was NOT validated as a result, (3) specific manual verification steps the user should perform. The lead agent treats PARTIAL as a blocker — incomplete validation is never silently accepted. diff --git a/.config/opencode/dcp.jsonc b/.config/opencode/dcp.jsonc index d485be1..31be0a3 100644 --- a/.config/opencode/dcp.jsonc +++ b/.config/opencode/dcp.jsonc @@ -8,6 +8,9 @@ "enabled": true, "protectedTools": [], }, + "experimental": { + "allowSubAgents": true, + } "manualMode": { "enabled": false, "automaticStrategies": true, @@ -17,25 +20,6 @@ "turns": 4, }, "protectedFilePatterns": [], - "tools": { - "settings": { - "nudgeEnabled": true, - "nudgeFrequency": 10, - "contextLimit": 80%, - "protectedTools": [], - }, - "distill": { - "permission": "allow", - "showDistillation": false, - }, - "compress": { - "permission": "deny", - "showCompression": false, - }, - "prune": { - "permission": "allow", - }, - }, "strategies": { "deduplication": { "enabled": true, @@ -50,4 +34,8 @@ "protectedTools": [], }, }, + "compress": { + "maxContextLimit": "80%", + "minContextLimit": "50%" + } } diff --git a/.config/opencode/opencode.jsonc b/.config/opencode/opencode.jsonc index 7b18dcb..e5f69fd 100644 --- a/.config/opencode/opencode.jsonc +++ b/.config/opencode/opencode.jsonc @@ -31,7 +31,7 @@ "playwright": { "type": "local", "command": [ - "npx", + "bunx", "@playwright/mcp@latest", "--headless", "--browser", @@ -40,13 +40,24 @@ "enabled": true }, "basic-memory": { + "type": "local", + "command": ["uvx", "basic-memory", "mcp"], + "enabled": true + }, + "ast-grep": { "type": "local", "command": [ "uvx", - "basic-memory", - "mcp" + "--from", + "git+https://github.com/ast-grep/ast-grep-mcp", + "ast-grep-server" ], "enabled": true + }, + "codebase-memory": { + "type": "local", + "command": ["codebase-memory-mcp", "mcp"], + "enabled": true } } } diff --git a/.config/opencode/skills/creating-agents/SKILL.md b/.config/opencode/skills/creating-agents/SKILL.md new file mode 100644 index 0000000..66cb110 --- /dev/null +++ b/.config/opencode/skills/creating-agents/SKILL.md @@ -0,0 +1,66 @@ +--- +name: creating-agents +description: Create or update opencode agents in this repository, including dispatch permissions and roster alignment requirements +permalink: opencode-config/skills/creating-agents/skill +--- + +# Creating Agents + +Use this skill when you need to add or revise an agent definition in this repo. + +## Agents vs Skills + +- **Agents** define runtime behavior and permissions in `agents/*.md`. +- **Skills** are reusable instruction modules under `skills/*/SKILL.md`. +- Do not treat agent creation as skill creation; each has different files and checks. + +## Source of Truth + +1. Agent definition file: `agents/.md` +2. Dispatch permissions for new dispatchable agents: `agents/lead.md` + - `permission.task.: allow` must be present for lead dispatch. +3. Human-readable roster: `AGENTS.md` + - Keep the roster table synchronized with actual agent files. +4. Runtime overrides: `opencode.jsonc` + - May override/disable agent behavior. + - Does **not** register a new agent. + +## Agent File Conventions + +For `agents/.md`: + +- Use frontmatter first, then concise role instructions. +- Keep tone imperative and operational. +- Include only permissions and behavior needed for the role. +- Align with existing files such as `agents/lead.md` and `agents/coder.md`. + +Typical frontmatter fields in this repo include: + +- `description` +- `mode` +- `model` (for subagents where needed) +- `temperature` +- `permission` +- `permalink` + + Mirror nearby agent files instead of inventing new metadata patterns. + Note: `agents/lead.md` is the only `mode: primary` agent. New agents should normally mirror a comparable subagent and use `mode: subagent` with an explicit `model`. + +## Practical Workflow (Create or Update) + +1. Inspect `agents/lead.md` and at least one similar `agents/*.md` file. +2. Create or edit `agents/.md` with matching local structure. +3. If the agent must be dispatchable, add `permission.task.: allow` in `agents/lead.md`. +4. Update `AGENTS.md` roster entry to match the new/updated agent. +5. Review `opencode.jsonc` for conflicting overrides/disable flags. + +## Manual Verification Checklist (No Validation Script) + +Run this checklist before claiming completion: + +- [ ] `agents/.md` exists and frontmatter is valid/consistent with peers. +- [ ] Agent instructions clearly define role, scope, and constraints. +- [ ] `agents/lead.md` includes `permission.task.: allow` if dispatch is required. +- [ ] `AGENTS.md` roster row exists and matches agent name/role/model. +- [ ] `opencode.jsonc` does not unintentionally disable or override the new agent. +- [ ] Terminology stays consistent: agents in `agents/*.md`, skills in `skills/*/SKILL.md`. diff --git a/.config/opencode/skills/creating-skills/SKILL.md b/.config/opencode/skills/creating-skills/SKILL.md new file mode 100644 index 0000000..777fab0 --- /dev/null +++ b/.config/opencode/skills/creating-skills/SKILL.md @@ -0,0 +1,64 @@ +--- +name: creating-skills +description: Create or update opencode skills in this repository using the required SKILL.md format and concise, trigger-focused guidance +permalink: opencode-config/skills/creating-skills/skill +--- + +# Creating Skills + +Use this skill when you need to add or revise an opencode skill under `skills/`. + +## Skills vs OpenAI/Codex Source Model + +- Treat this repo as **opencode-native**. +- Do **not** use OpenAI/Codex-specific artifacts such as `agents/openai.yaml`, `init_skill.py`, `quick_validate.py`, or `scripts/references/assets` conventions from the old source model. +- A skill is discovered from `skills/*/SKILL.md` only. + +## Required Structure + +1. Create a folder at `skills//`. +2. Add `skills//SKILL.md`. +3. Keep `` equal to frontmatter `name`. + +Frontmatter must contain only: + +```yaml +--- +name: +description: +permalink: opencode-config/skills//skill +--- +``` + +## Naming Rules + +- Use lowercase kebab-case. +- Keep names short and action-oriented. +- Match folder name and `name` exactly. + +## Body Writing Rules + +- Write concise, imperative instructions. +- Lead with when to load and the core workflow. +- Prefer short checklists over long prose. +- Include only repo-relevant guidance. + +## Companion Notes (`*.md` in skill folder) + +Add companion markdown files only when detail would bloat `SKILL.md` (examples, deep procedures, edge-case references). + +- Keep `SKILL.md` as the operational entrypoint. +- Link companion files directly from `SKILL.md` with clear “when to read” guidance. +- Do not create extra docs by default. + +## Practical Workflow (Create or Update) + +1. Inspect 2–3 nearby skills for local style and brevity. +2. Pick/update `` and folder path under `skills/`. +3. Write or revise `SKILL.md` frontmatter (`name`, `description`, `permalink` only). +4. Draft concise body sections: purpose, load conditions, workflow, red flags/checks. +5. Add minimal companion `.md` files only if needed; link them from `SKILL.md`. +6. Verify discovery path and naming consistency: + - file exists at `skills//SKILL.md` + - folder name == frontmatter `name` + - no OpenAI/Codex-only artifacts introduced diff --git a/.gitconfig b/.gitconfig index a2b51c9..4412fd6 100644 --- a/.gitconfig +++ b/.gitconfig @@ -6,6 +6,4 @@ helper = !/usr/bin/gh auth git-credential [user] email = alexander@wiesner.com.br - name = alex -[init] - defaultBranch = main + name = alex wiesner diff --git a/.local/bin/clipboard-menu b/.local/bin/clipboard-menu deleted file mode 100755 index 1a64fc4..0000000 --- a/.local/bin/clipboard-menu +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -# Clipboard menu using cliphist and rofi - -selection=$(cliphist list | rofi -dmenu -p "Clipboard") - -# Only copy if something was actually selected -if [ -n "$selection" ]; then - echo "$selection" | cliphist decode | wl-copy -fi diff --git a/.memory/decisions.md b/.memory/decisions.md index 5e5489f..9c02685 100644 --- a/.memory/decisions.md +++ b/.memory/decisions.md @@ -1,3 +1,9 @@ +--- +title: decisions +type: note +permalink: dotfiles/decisions +--- + # Dotfiles Decisions ## Desktop Environment: Hyprland + Wayland @@ -56,4 +62,4 @@ ## No Global `.gitignore` in Dotfiles - **Observation:** No global gitignore file visible; tracking is managed per-repo -- **Pattern:** Sensitive SSH private key `.ssh/id_ed25519` is tracked — implies this repo may use filesystem permissions for security +- **Pattern:** Sensitive SSH private key `.ssh/id_ed25519` is tracked — implies this repo may use filesystem permissions for security \ No newline at end of file diff --git a/.memory/decisions/critic-gate-tmux-shift-enter-fix.md b/.memory/decisions/critic-gate-tmux-shift-enter-fix.md new file mode 100644 index 0000000..e54fb79 --- /dev/null +++ b/.memory/decisions/critic-gate-tmux-shift-enter-fix.md @@ -0,0 +1,31 @@ +--- +title: critic-gate-tmux-shift-enter-fix +type: note +permalink: dotfiles/decisions/critic-gate-tmux-shift-enter-fix +tags: +- tmux +- critic-gate +- approved +--- + +# Critic Gate: tmux Shift+Enter Fix + +## Verdict +- [decision] APPROVED — Plan is minimal, correctly scoped, and non-destructive. + +## Rationale +- Single `bind-key -n S-Enter send-keys "\n"` addition to `~/.tmux.conf`. +- `extended-keys on` (line 8) and `extkeys` terminal feature (line 9) already present — `S-Enter` will be recognised. +- No existing conflicting bindings in `.tmux.conf`. +- Config will load cleanly; standard tmux syntax. + +## Assumption Challenges +- [finding] `S-Enter` key name is valid because extended-keys is already enabled. ✅ +- [finding] `send-keys "\n"` sends LF (0x0A). For TUI apps and multi-line tools, this inserts a newline as intended. For bare shell prompts, LF may still trigger accept-line (same as Enter). No shell-side `bindkey` exists in `.zshrc` to differentiate. This is a known limitation, not a blocker — follow-up zle binding may be needed. + +## Files Evaluated +- `/home/alex/dotfiles/.tmux.conf` (57 lines, all relevant config) +- `/home/alex/dotfiles/.zshrc` (2 lines, no keybindings) + +## Relations +- gates [[tmux-shift-enter-fix]] \ No newline at end of file diff --git a/.memory/gates/gate-tmux-shift-enter-fix-review.md b/.memory/gates/gate-tmux-shift-enter-fix-review.md new file mode 100644 index 0000000..447554b --- /dev/null +++ b/.memory/gates/gate-tmux-shift-enter-fix-review.md @@ -0,0 +1,33 @@ +--- +title: gate-tmux-shift-enter-fix-review +type: note +permalink: dotfiles/gates/gate-tmux-shift-enter-fix-review +tags: +- tmux +- review +- gate +- approved +--- + +# Gate: tmux Shift+Enter Fix — Correctness Review + +## Verdict +- [decision] APPROVED — REVIEW_SCORE: 0 + +## Findings +- [observation] No CRITICAL or WARNING issues found. +- [observation] `bind-key -n S-Enter send-keys "\n"` is semantically correct for the stated intent. +- [observation] Prerequisite `extended-keys on` is present and positioned before the binding. +- [observation] Terminal features line (`xterm-kitty:extkeys`) enables the terminal to report extended key sequences. +- [observation] No conflicting bindings exist in the config. +- [observation] Config ordering is correct — prerequisites before the binding. + +## Evidence Checked +- [observation] Line 8: `set -s extended-keys on` — enables tmux to recognize modified keys like `S-Enter`. +- [observation] Line 9: `set -as terminal-features 'xterm-kitty:extkeys'` — tells tmux the terminal supports extended keys. +- [observation] Line 10: `bind-key -n S-Enter send-keys "\n"` — root-table binding, sends literal newline. Correct. +- [observation] No other `Enter`-related or `S-Enter` bindings exist that could conflict. +- [observation] `-n` flag correctly targets root table (no prefix key needed). + +## Relations +- reviews [[plans/tmux-shift-enter-fix]] \ No newline at end of file diff --git a/.memory/knowledge.md b/.memory/knowledge.md index 1e05329..bd76948 100644 --- a/.memory/knowledge.md +++ b/.memory/knowledge.md @@ -1,3 +1,9 @@ +--- +title: knowledge +type: note +permalink: dotfiles/knowledge +--- + # Dotfiles Knowledge ## Project Purpose @@ -185,4 +191,4 @@ File: `.gitconfig` - `user.name=alex`, `user.email=misc@wiesner.com.br` - `init.defaultBranch=main` -- Credential helper: `!/usr/bin/gh auth git-credential` (GitHub + Gist) +- Credential helper: `!/usr/bin/gh auth git-credential` (GitHub + Gist) \ No newline at end of file diff --git a/.memory/plans/fix-github-push-large-binary.md b/.memory/plans/fix-github-push-large-binary.md new file mode 100644 index 0000000..4e179b7 --- /dev/null +++ b/.memory/plans/fix-github-push-large-binary.md @@ -0,0 +1,33 @@ +--- +title: fix-github-push-large-binary +type: note +permalink: dotfiles/plans/fix-github-push-large-binary +tags: +- git +- risk +- tooling +--- + +# Fix GitHub Push Rejection for Large Binary + +**Goal:** Remove the oversized `.local/bin/codebase-memory-mcp` blob from local-only history so `main` can push to GitHub successfully. + +## Root cause +- [decision] Commit `969140e` added `.local/bin/codebase-memory-mcp` at ~143.51 MB. +- [decision] Commit `2643a0a` later removed the file, but the blob still exists in local history, so GitHub rejects the push. + +## Tasks +- [ ] Rewrite the 4 local-only commits by soft-resetting to `origin/main`. +- [ ] Recreate a clean commit set without the large binary in history. +- [ ] Verify no large-file path remains in reachable history. +- [ ] Retry `git push` and confirm success. + +## Acceptance criteria +- No reachable commit from `HEAD` contains `.local/bin/codebase-memory-mcp`. +- `git push` to `origin/main` succeeds without GitHub large-file rejection. + +## Pre-mortem +- Most likely failure: recommit accidentally stages a regenerated large binary again. +- Fragile assumption: current worktree is clean except for the 4 local-only commits. +- Red flag requiring redesign: if the large blob exists in earlier shared history, a broader history rewrite would be required. +- Easy-to-miss regression: leaving `.local/bin/codebase-memory-mcp` unignored so it gets re-added later. diff --git a/.memory/plans/luks-sddm-kwallet-login-integration.md b/.memory/plans/luks-sddm-kwallet-login-integration.md new file mode 100644 index 0000000..ff273de --- /dev/null +++ b/.memory/plans/luks-sddm-kwallet-login-integration.md @@ -0,0 +1,43 @@ +--- +title: luks-sddm-kwallet-login-integration +type: note +permalink: dotfiles/plans/luks-sddm-kwallet-login-integration +tags: +- auth +- sddm +- kwallet +- luks +--- + +# LUKS / SDDM / KWallet login integration + +## Goal +Configure the system so login feels unified across LUKS boot unlock, SDDM, and KWallet. + +## Clarified scope +- [decision] User selected **Password login** instead of true SDDM autologin because password login preserves KWallet PAM unlock. +- [decision] User selected **Just document commands** instead of expanding repo scope to manage `/etc` files directly. +- [decision] Deliverable is repo documentation with exact manual system commands/edits; no tracked `/etc` files will be added in this change. + +## Discovery +- Dotfiles repo contains user-space config only; system auth files live outside the repo. +- Current system already references `pam_kwallet5.so` in `/etc/pam.d/sddm` and `/etc/pam.d/sddm-autologin`, but the module is missing and silently skipped. +- `kwallet-pam` is available in Arch repos and should provide the current PAM module for KWallet 6. +- LUKS unlock and SDDM login are independent phases; there is no direct password handoff from initramfs to SDDM. +- True SDDM autologin conflicts with password-based KWallet unlock because no login password is available to PAM during autologin. + +## Tasks +- [ ] Write documentation for package install and PAM edits needed for SDDM/KWallet integration +- [ ] Document wallet initialization and verification steps +- [ ] Review documentation for correctness and scope alignment +- [ ] Validate documented commands against current system state where possible +- [ ] Check documentation coverage/placement in repo + +## Acceptance criteria +- README documents the exact package install step and the exact PAM module substitutions needed. +- README explicitly states that password login is the chosen model and true SDDM autologin is not part of this setup. +- README includes KWallet initialization and verification steps suitable for this Arch + Hyprland + SDDM setup. +- Reviewer/tester/librarian passes are recorded before completion. + +## Workstream +- Single workstream in the main repo working tree. diff --git a/.memory/plans/tmux-shift-enter-fix.md b/.memory/plans/tmux-shift-enter-fix.md new file mode 100644 index 0000000..35ddaf6 --- /dev/null +++ b/.memory/plans/tmux-shift-enter-fix.md @@ -0,0 +1,37 @@ +--- +title: tmux-shift-enter-fix +type: plan +permalink: dotfiles/plans/tmux-shift-enter-fix +tags: +- tmux +- terminal +- keybindings +--- + +# tmux Shift+Enter Fix + +## Goal +Inside tmux, pressing Shift+Enter should insert a literal newline instead of submitting the command line. + +## Decision +- [decision] Preserve tmux extended-keys support and apply the smallest possible fix at the tmux layer. +- [decision] Use `bind-key -n S-Enter send-keys "\n"` in `~/.tmux.conf` instead of disabling `extended-keys` or adding shell-specific bindings. + +## Tasks +- [ ] Add a tmux root-table binding for `S-Enter` +- [ ] Verify tmux loads the config and exposes the expected binding +- [ ] Check documentation coverage for this config tweak + +## Acceptance criteria +- `~/.tmux.conf` contains an explicit `S-Enter` binding that sends a newline. +- Existing `extended-keys` settings remain enabled. +- After sourcing the config, tmux shows the `S-Enter` root binding. + +## Workstream +- Single workstream in the main repo working tree. + +## Findings tracker +- None. + +## Relations +- related_to [[knowledge]] \ No newline at end of file diff --git a/.memory/research/LUKS SDDM KWallet discovery.md b/.memory/research/LUKS SDDM KWallet discovery.md new file mode 100644 index 0000000..f6a5b4c --- /dev/null +++ b/.memory/research/LUKS SDDM KWallet discovery.md @@ -0,0 +1,156 @@ +--- +title: LUKS SDDM KWallet discovery +type: note +permalink: dotfiles/research/luks-sddm-kwallet-discovery +tags: +- sddm +- kwallet +- luks +- pam +- arch +- hyprland +- discovery +--- + +# LUKS SDDM KWallet discovery + +## System context + +- [fact] Distribution: **Arch Linux** (rolling), NOT NixOS — all configuration is manual files or pacman packages +- [fact] Desktop environment: **Hyprland** (Wayland compositor), NOT KDE Plasma +- [fact] Display manager: **SDDM** (installed, PAM files present) +- [fact] Lock screen: **hyprlock** (Hyprland native, separate from SDDM) +- [fact] Default session: `Session=hyprland` (from `~/.dmrc`) +- [fact] Boot: **systemd-boot** (`/boot/loader/`), kernel cmdline has `cryptdevice=PARTUUID=1a555ca6-ea08-4128-80cf-fe213664030e:root root=/dev/mapper/root` +- [fact] LUKS encryption: **LUKS-encrypted root** (`encrypt` hook in mkinitcpio), initramfs uses classic `encrypt` hook (not `sd-encrypt`) +- [fact] Filesystem: **btrfs** with `@` subvolume + +## Current config files inventory + +### Dotfiles repo (`/home/alex/dotfiles`) — user scope only + +| File | Contents | +|---|---| +| `.config/hypr/hyprland.conf` | Hyprland WM config; autostart: waybar + nm-applet; lock bind: `hyprlock` | +| `.config/hypr/hyprlock.conf` | hyprlock PAM-auth lock screen; Catppuccin Mocha theme | +| `.config/hypr/monitors.conf` | Monitor config | +| `.config/hypr/workspaces.conf` | Workspace rules | +| `.dmrc` | `Session=hyprland` | +| `.gitconfig` | Git identity only | +| `.config/fish/`, `.config/nvim/`, etc. | Shell and editor config, not relevant | + +**The dotfiles repo does NOT contain any SDDM, PAM, mkinitcpio, bootloader, or KWallet configuration.** All of those are system-level files managed outside this repo. + +### System-level files (outside dotfiles repo) + +| File | Status | Key contents | +|---|---|---| +| `/etc/mkinitcpio.conf` | Present | HOOKS include `encrypt` (classic LUKS hook) | +| `/boot/loader/entries/2026-03-11_16-58-39_linux.conf` | Present | `cryptdevice=PARTUUID=...` kernel param, LUKS root | +| `/boot/loader/loader.conf` | Present | `timeout 3`, no autologin | +| `/etc/pam.d/sddm` | Present | Includes `pam_kwallet5.so` (broken — see risks) | +| `/etc/pam.d/sddm-autologin` | Present | Includes `pam_kwallet5.so` (broken — see risks) | +| `/etc/pam.d/sddm-greeter` | Present | Standard greeter-only config | +| `/etc/pam.d/system-auth` | Present | Standard pam_unix, pam_faillock | +| `/etc/pam.d/system-login` | Present | Standard, includes pam_u2f.so at top | +| `/etc/pam.d/hyprlock` | Present | `auth include login` — delegates to login chain | +| `/usr/lib/sddm/sddm.conf.d/default.conf` | Present | No autologin configured; `DisplayServer=x11` (NOT wayland) | +| `/etc/sddm.conf.d/` | **MISSING** — no local overrides exist | No user customization of SDDM | +| `/etc/sddm.conf` | **MISSING** | No top-level SDDM config file | + +## KDE/KWallet installation state + +- [fact] `kwalletd6` binary is installed: `/usr/bin/kwalletd6` +- [fact] `kwallet-query` is installed: `/usr/bin/kwallet-query` +- [fact] **`pam_kwallet5.so` does NOT exist** in `/usr/lib/security/` or `/lib/security/` +- [fact] **`pam_kwallet6.so` does NOT exist** either — `kwallet-pam` package is NOT installed +- [fact] `pam_gnome_keyring.so` IS installed at `/usr/lib/security/` +- [fact] No `~/.config/kwalletrc` exists — KWallet has never been initialized for this user +- [fact] No `~/.local/share/kwalletd/` directory — no wallet database exists + +## Current PAM configuration for SDDM (detailed) + +### `/etc/pam.d/sddm` (normal login) +``` +auth sufficient pam_u2f.so cue +auth include system-login +-auth optional pam_gnome_keyring.so +-auth optional pam_kwallet5.so ← BROKEN: module not installed + +session optional pam_keyinit.so force revoke +session include system-login +-session optional pam_gnome_keyring.so auto_start +-session optional pam_kwallet5.so auto_start ← BROKEN +``` + +### `/etc/pam.d/sddm-autologin` +``` +auth sufficient pam_u2f.so cue +auth required pam_permit.so +-auth optional pam_kwallet5.so ← BROKEN +session include system-local-login +-session optional pam_kwallet5.so auto_start ← BROKEN +``` + +Note: The `-` prefix means these lines are silently skipped if the module is missing — not causing errors, but not functioning. + +## SDDM autologin configuration state + +- [fact] SDDM autologin is **NOT configured** — `User=` and `Session=` are empty in default.conf +- [fact] SDDM `DisplayServer=x11` in default.conf — **no wayland greeter configured** +- [fact] No `/etc/sddm.conf.d/` drop-in directory exists + +## Dependency chain for LUKS → SDDM → KWallet integration + +### Boot-time LUKS (currently working) +``` +systemd-boot → kernel cryptdevice= param → initramfs encrypt hook → LUKS passphrase prompt → root mounted +``` + +### Login-time (currently: manual SDDM login, no KWallet auto-open) +``` +SDDM greeter → user types password → PAM sddm → pam_unix validates → session started + → pam_kwallet5.so would unlock wallet (BROKEN: module missing) +``` + +### Target state (proposed) +``` +Boot: LUKS passphrase entered + → system up → SDDM greeter shown + → Option A (autologin): SDDM skips password → session starts → KWallet opened with stored key + → Option B (PAM reuse): SDDM password == user password == KWallet password → pam_kwallet6 unlocks wallet on login +``` + +## Likely edit points + +### To fix KWallet auto-open via PAM (Option B — recommended) +1. **Install `kwallet-pam` package** (AUR: `kwallet-pam` provides `pam_kwallet6.so`) — PREREQUISITE +2. **`/etc/pam.d/sddm`** — replace `pam_kwallet5.so` references with `pam_kwallet6.so` in auth and session stacks +3. **`/etc/pam.d/sddm-autologin`** — same replacement if autologin is also desired +4. **`~/.config/kwalletrc`** — create/configure wallet to use blowfish or GPG encryption; set wallet name +5. **Initialize wallet** — run `kwalletd6` or use `kwallet-query` to create the default wallet with the user's login password as the unlock password + +### To configure SDDM for Wayland session (currently X11 default) +6. **`/etc/sddm.conf.d/hyprland.conf`** (new file) — set `DisplayServer=wayland` or leave X11 and use Wayland session via `wayland-session` script + +### To configure SDDM autologin (Option A) +7. **`/etc/sddm.conf.d/autologin.conf`** (new file) — set `User=alex`, `Session=hyprland` + +### To track these system files in the dotfiles repo +8. Add symlinks or a deploy script — system PAM files are outside the current dotfiles scope + +## Risks and ambiguities + +- [risk] **`pam_kwallet5.so` vs `pam_kwallet6.so` mismatch**: PAM files reference kwallet5 module; installed binary is kwalletd6. The `kwallet-pam` package for KF6 provides `pam_kwallet6.so` — this must be installed from AUR or a compatible repo. +- [risk] **No KDE Plasma installed**: The system uses Hyprland, not Plasma. KWallet works standalone, but Plasma's system tray integration for wallet prompts won't be present. Apps must use the KWallet D-Bus API directly. +- [risk] **SDDM running X11 compositor by default**: The `default.conf` has `DisplayServer=x11`, but the user session is Hyprland (Wayland). SDDM itself can still launch Wayland sessions from an X11 greeter. This works but is a mismatch worth documenting. +- [risk] **autologin + KWallet security trade-off**: If autologin is used (Option A), KWallet cannot be unlocked by the user password (there is none at login). The wallet would need to be set to "no password" (plaintext) or use a keyfile — both reduce security. +- [risk] **pam_u2f.so at top of system-login and sddm**: U2F is configured as `sufficient` — meaning a hardware key can bypass password entirely. This could bypass KWallet unlock if the wallet password differs from the user password. +- [risk] **hyprlock uses `auth include login`**: The lock screen delegates to the `login` PAM chain, which does NOT include kwallet PAM modules. Unlocking hyprlock will NOT re-open the wallet. +- [risk] **Dotfiles repo scope boundary**: `/etc/pam.d/`, `/etc/sddm.conf.d/`, `/etc/mkinitcpio.conf`, and `/boot/loader/` are all outside the dotfiles repo. These are system files. Either the dotfiles repo needs to expand its scope (with a deploy script), or these changes must be managed separately. +- [risk] **mkinitcpio uses classic `encrypt` hook, not `sd-encrypt`**: The `sd-encrypt` (systemd) hook supports TPM2/FIDO2-bound LUKS keys for automatic unlock; the classic `encrypt` hook does not. If the goal involves TPM2-bound auto-unlock (true single-passphrase boot), migration to `sd-encrypt` would be required. +- [ambiguity] **"SDDM login" with LUKS**: LUKS unlock happens at boot (initramfs), before SDDM. There is no mechanism for SDDM to "reuse" the LUKS passphrase directly. The integration point is: user types the same password at SDDM → PAM propagates it to `pam_kwallet6` → wallet unlocked. The LUKS and SDDM passwords are independent unless deliberately set to the same value. + +## Relations +- related_to [[Hyprland config]] +- related_to [[PAM configuration]] diff --git a/.memory/research/LUKS SDDM KWallet documentation targets.md b/.memory/research/LUKS SDDM KWallet documentation targets.md new file mode 100644 index 0000000..d4f2653 --- /dev/null +++ b/.memory/research/LUKS SDDM KWallet documentation targets.md @@ -0,0 +1,63 @@ +--- +title: LUKS SDDM KWallet documentation targets +type: note +permalink: dotfiles/research/luks-sddm-kwallet-documentation-targets +tags: +- sddm +- kwallet +- luks +- pam +- documentation +- edit-points +--- + +# LUKS SDDM KWallet documentation targets + +## Summary + +User decision: **document exact commands only** (not manage `/etc` files in the repo). This means the deliverable is a new documentation file in the dotfiles repo, not new symlinks or deploy scripts. + +## Repo documentation conventions found + +- [fact] **No README.md, SETUP.md, INSTALL.md, or docs/ directory exists** — the dotfiles repo has no human-facing setup documentation at all +- [fact] The only markdown files tracked in git are: `.memory/decisions.md`, `.memory/knowledge.md`, `.memory/research/opencode-architecture.md` — all are basic-memory agent-facing notes, not user-facing docs +- [fact] `.config/opencode/AGENTS.md` is the OpenCode agent instruction file (global AI config) — NOT a per-feature setup doc +- [convention] There is no established convention for "machine setup" documentation in this repo — **any new docs file will establish the pattern** + +## Best file location for command documentation + +### Option A (Recommended): `README.md` at repo root +- **Path:** `/home/alex/dotfiles/README.md` +- **Rationale:** Establishes the first user-facing doc for the repo; natural home for setup and system integration notes; visible on any git host +- **Section to add:** `## System Setup: KWallet + SDDM PAM integration` with step-by-step commands + +### Option B: `.memory/plans/luks-sddm-kwallet-login-integration.md` (append) +- **Path:** `/home/alex/dotfiles/.memory/plans/luks-sddm-kwallet-login-integration.md` +- **Rationale:** Already tracks this feature; append a `## Exact commands` section +- **Downside:** `.memory/` files are agent-facing, not user-facing; commands buried in plan notes are harder to find later + +### Option C: New dedicated file `SETUP-auth.md` or `docs/auth-setup.md` +- **Path:** `/home/alex/dotfiles/SETUP-auth.md` +- **Rationale:** Keeps system-setup docs separate from repo README +- **Downside:** Fragments documentation without an established convention + +## What the documentation must cover (per plan + discovery) + +Commands for: +1. `pacman -S kwallet-pam` OR AUR install of `kwallet-pam` (provides `pam_kwallet6.so`) +2. Edit `/etc/pam.d/sddm` — replace `pam_kwallet5.so` with `pam_kwallet6.so` (auth + session lines) +3. Edit `/etc/pam.d/sddm-autologin` — same replacement (if needed) +4. Create `/etc/sddm.conf.d/` directory if missing +5. Initialize KWallet — `kwalletd6` first-run or `kwallet-query` commands +6. Verify: `systemctl restart sddm` and login test + +## Risks relevant to documentation + +- [risk] `kwallet-pam` for KF6 may be AUR-only on Arch — exact package name needs verification before documenting +- [risk] `/etc/pam.d/` edits require root; if documented as copy-paste commands, must be prefixed with `sudo` +- [risk] SDDM autologin is NOT configured and should NOT be added — the password-login model was chosen; docs must not inadvertently suggest autologin setup +- [risk] A new `README.md` will be the first user-facing documentation and will set precedent — scope it carefully to avoid bloat + +## Relations +- related_to [[LUKS SDDM KWallet discovery]] +- related_to [[luks-sddm-kwallet-login-integration]] diff --git a/.memory/research/SDDM KWallet PAM Setup for Hyprland.md b/.memory/research/SDDM KWallet PAM Setup for Hyprland.md new file mode 100644 index 0000000..05197c1 --- /dev/null +++ b/.memory/research/SDDM KWallet PAM Setup for Hyprland.md @@ -0,0 +1,264 @@ +--- +title: SDDM KWallet PAM Setup for Hyprland +type: note +permalink: dotfiles/research/sddm-kwallet-pam-setup-for-hyprland +tags: +- sddm +- kwallet +- pam +- hyprland +- arch +- research +- authoritative +--- + +# SDDM KWallet PAM Setup for Hyprland + +## Summary + +Complete, source-verified setup for automatic KWallet unlock on SDDM password login, for a non-Plasma (Hyprland) Arch Linux system. + +## Freshness +- confidence: high +- last_validated: 2026-03-11 +- volatility: low (KDE Plasma 6 PAM module is stable; Arch Wiki last edited 2026-03-10) +- review_after_days: 90 +- validation_count: 1 +- contradiction_count: 0 + +## Sources consulted +- [source] Arch Wiki "KDE Wallet" — https://wiki.archlinux.org/title/KDE_Wallet (last edited 2026-03-10) +- [source] Arch Wiki "SDDM" — https://wiki.archlinux.org/title/SDDM (last edited 2026-03-04) +- [source] Arch package database `kwallet-pam` 6.6.2-1 file listing — https://archlinux.org/packages/extra/x86_64/kwallet-pam/files/ +- [source] Arch package database `kwallet` 6.23.0-1 file listing — https://archlinux.org/packages/extra/x86_64/kwallet/files/ +- [source] Real-world Hyprland dotfiles from GitHub (wayblueorg/wayblue, AhmedAmrNabil/nix-config) + +## (1) Package to install + +- [fact] Package: **`kwallet-pam`** — in the official **`extra`** repository (NOT AUR) +- [fact] Install command: `sudo pacman -S kwallet-pam` +- [fact] Current version: **6.6.2-1** (as of 2026-03-03) +- [fact] Dependencies: `kwallet`, `pam`, `libgcrypt`, `socat` (all already present or auto-resolved) +- [fact] Files installed: + - `/usr/lib/security/pam_kwallet5.so` — the PAM module + - `/usr/lib/pam_kwallet_init` — session-start helper script + - `/etc/xdg/autostart/pam_kwallet_init.desktop` — XDG autostart for Plasma/DE environments + - `/usr/lib/systemd/user/plasma-kwallet-pam.service` — systemd user service + +### Critical naming fact +- [fact] **The PAM module is `pam_kwallet5.so` even for KDE Frameworks 6 / Plasma 6.** There is no `pam_kwallet6.so`. The "5" in the name is a legacy artifact. The previous discovery note incorrectly stated `pam_kwallet6.so` would be provided — this was wrong. +- [fact] The existing `/etc/pam.d/sddm` and `/etc/pam.d/sddm-autologin` files already reference `pam_kwallet5.so` — they just need the package installed; **no module name changes are needed**. + +## (2) PAM configuration + +### Plasma 6 / ksecretd consideration + +The Arch Wiki (section "Configure PAM on Plasma 6 (KF6)", updated 2026-03-10) says Plasma 6 uses `ksecretd` as the secret service daemon. The PAM session line should include `kwalletd=/usr/bin/ksecretd` to point to the new daemon. + +- [fact] `ksecretd` binary is at `/usr/bin/ksecretd` and is shipped by the `kwallet` package (6.23.0-1) +- [fact] `kwalletd6` binary is at `/usr/bin/kwalletd6` and is also in the `kwallet` package +- [decision] For a non-Plasma Hyprland setup, the question is which daemon to target. The Arch Wiki recommends `kwalletd=/usr/bin/ksecretd` for KF6. Since the user has `kwalletd6` and `ksecretd` both installed via the `kwallet` package, and the Arch Wiki explicitly documents this parameter for KF6, the documentation should use the `kwalletd=/usr/bin/ksecretd` parameter. + +### Recommended `/etc/pam.d/sddm` (password login) + +The file already has the right structure. After installing `kwallet-pam`, the existing lines become functional. However, for Plasma 6 / KF6 compatibility, the session line should add the `kwalletd=` parameter: + +``` +#%PAM-1.0 + +auth sufficient pam_u2f.so cue +auth include system-login +-auth optional pam_gnome_keyring.so +-auth optional pam_kwallet5.so + +account include system-login + +password include system-login + +session optional pam_keyinit.so force revoke +session include system-login +-session optional pam_gnome_keyring.so auto_start +-session optional pam_kwallet5.so auto_start kwalletd=/usr/bin/ksecretd +``` + +Key points: +- [fact] The `-` prefix on `-auth` and `-session` lines means "skip silently if module is missing" — this is already present in the default SDDM PAM files +- [fact] The `auth` line captures the user password for later use by the session line +- [fact] The `session` line with `auto_start` tells the module to start kwalletd/ksecretd and unlock the wallet +- [fact] `kwalletd=/usr/bin/ksecretd` directs the module to use KF6's ksecretd daemon instead of the legacy kwalletd5 + +### Recommended `/etc/pam.d/sddm-autologin` + +This file is for SDDM autologin ONLY. Since the chosen model is password login, this file is informational but should still be kept correct: + +``` +#%PAM-1.0 + +auth sufficient pam_u2f.so cue +auth required pam_permit.so +-auth optional pam_kwallet5.so + +account include system-local-login + +password include system-local-login + +session include system-local-login +-session optional pam_kwallet5.so auto_start kwalletd=/usr/bin/ksecretd +``` + +- [caveat] Autologin skips password entry → PAM has no password to pass to `pam_kwallet5.so` → wallet cannot be unlocked unless LUKS passphrase forwarding is used (see section 5) + +### Minimal edit needed for existing system + +Since the existing `/etc/pam.d/sddm` already has `pam_kwallet5.so` lines, the only change needed is: + +1. Install `kwallet-pam` (makes the module file appear at `/usr/lib/security/pam_kwallet5.so`) +2. Add `kwalletd=/usr/bin/ksecretd` to the session line for KF6 compatibility + +The auth line does NOT need the `kwalletd=` parameter — only the session line does. + +## (3) Wallet initialization for non-Plasma (Hyprland) users + +### Step A: Create the wallet + +The wallet **must** be named `kdewallet` (the default name). PAM unlock only works with this specific wallet name. + +**Option 1 — GUI (recommended if kwalletmanager is available):** +```bash +sudo pacman -S kwalletmanager +kwalletmanager6 +``` +Then: File > New Wallet > name it `kdewallet` > set password to match login password > choose **blowfish** encryption (NOT GPG). + +**Option 2 — Headless/CLI:** +No pure-CLI wallet creation tool exists. The wallet is created automatically when: +1. The PAM module is installed and configured +2. The user logs in via SDDM with password +3. `pam_kwallet_init` runs and kwalletd6/ksecretd starts +4. If no wallet exists, kwalletd6 creates one on first access + +For a truly headless init, trigger it by running in the session: +```bash +# Ensure kwalletd6/ksecretd is running (D-Bus activated) +dbus-send --session --dest=org.kde.kwalletd6 --print-reply \ + /modules/kwalletd6 org.kde.KWallet.open \ + string:"kdewallet" int64:0 string:"init" +``` +This prompts for the wallet password interactively (Qt dialog). + +### Step B: Ensure wallet password matches login password + +- [requirement] The KWallet password MUST be identical to the Unix user login password. PAM passes the login password to the kwallet module; if they differ, the wallet won't unlock. +- [requirement] If the user password is changed later, the wallet password must be updated to match. Use `kwalletmanager6` > Change Password, or delete and recreate the wallet. + +### Step C: kwalletrc configuration + +Create `~/.config/kwalletrc` if it doesn't exist: + +```ini +[Wallet] +Default Wallet=kdewallet +Enabled=true +First Use=false + +[org.freedesktop.secrets] +apiEnabled=true +``` + +The `apiEnabled=true` setting enables the org.freedesktop.secrets D-Bus API, allowing libsecret-based apps (Chromium, VSCode, etc.) to use KWallet. + +### Step D: Autostart `pam_kwallet_init` in Hyprland + +The `kwallet-pam` package installs an XDG autostart entry (`/etc/xdg/autostart/pam_kwallet_init.desktop`), but Hyprland does NOT process XDG autostart files by default. + +Add to `~/.config/hypr/hyprland.conf`: +``` +exec-once = /usr/lib/pam_kwallet_init +``` + +This script reads the PAM-cached credentials and passes them to kwalletd6/ksecretd to unlock the wallet. + +### Step E: D-Bus activation service (optional but recommended) + +Create `~/.local/share/dbus-1/services/org.freedesktop.secrets.service`: +```ini +[D-BUS Service] +Name=org.freedesktop.secrets +Exec=/usr/bin/kwalletd6 +``` + +This ensures kwalletd6 auto-starts when any app requests secrets via D-Bus, even before the wallet is explicitly opened. + +## (4) Verification + +### Quick verification after login + +```bash +# 1. Check the PAM module is installed +ls -la /usr/lib/security/pam_kwallet5.so + +# 2. Check kwalletd6 or ksecretd is running +pgrep -a kwalletd6 || pgrep -a ksecretd + +# 3. Check the wallet is open +dbus-send --session --dest=org.kde.kwalletd6 --print-reply \ + /modules/kwalletd6 org.kde.KWallet.isOpen \ + string:"kdewallet" + +# 4. Check wallet files exist +ls -la ~/.local/share/kwalletd/ + +# 5. Query the wallet (should return without prompting for password) +kwallet-query -l kdewallet + +# 6. Check environment variables set by pam_kwallet_init +echo $PAM_KWALLET5_LOGIN +``` + +### Full integration test +1. Log out of Hyprland +2. At SDDM greeter, type user password and log in +3. After Hyprland starts, run `kwallet-query -l kdewallet` — it should list folders without prompting +4. Open a KWallet-aware app (e.g., Chromium with `--password-store=kwallet5`) and verify it stores/retrieves credentials + +### Troubleshooting if wallet doesn't auto-unlock +- Check `journalctl --user -u plasma-kwallet-pam.service` for errors +- Check `journalctl -b | grep -i kwallet` for PAM-level errors +- Verify wallet password matches login password exactly +- Verify wallet is named exactly `kdewallet` (not `default` or any other name) +- Verify wallet uses blowfish encryption, not GPG + +## (5) Caveats + +### U2F / pam_u2f.so interaction + +- [risk] The existing `/etc/pam.d/sddm` has `auth sufficient pam_u2f.so cue` as the FIRST auth line. When `sufficient` succeeds, PAM skips remaining auth modules — including `pam_kwallet5.so`. +- [consequence] If the user authenticates via U2F key only (no password typed), the kwallet module never captures a password → wallet cannot be unlocked automatically. +- [mitigation] This is acceptable if U2F is used as a convenience shortcut and the user accepts that wallet won't auto-unlock in that case. The wallet can be manually unlocked later. +- [alternative] To make U2F + kwallet work together, change `sufficient` to a two-factor setup where password is always required. But this changes the security model and is out of scope for this documentation. + +### Autologin caveat + +- [risk] SDDM autologin (`pam_permit.so`) provides no password → `pam_kwallet5.so` has nothing to unlock the wallet with. +- [fact] The Arch Wiki documents a workaround using `pam_systemd_loadkey.so` for LUKS-encrypted systems: the LUKS passphrase can be forwarded from the initramfs to the PAM stack, allowing wallet unlock even with autologin. +- [requirement] This requires: (1) systemd-based initramfs (`sd-encrypt` hook, not classic `encrypt`), (2) `pam_systemd_loadkey.so` line in sddm-autologin, (3) sddm.service override with `KeyringMode=inherit`. +- [fact] The current system uses classic `encrypt` hook, NOT `sd-encrypt`, so this workaround is NOT available without migrating the initramfs to systemd hooks. +- [decision] Since password login (not autologin) was chosen, this is informational only. + +### Fingerprint reader caveat +- [fact] KWallet cannot be unlocked using a fingerprint reader (per Arch Wiki). Similar to U2F — no password is available. + +### GPG encryption caveat +- [fact] `kwallet-pam` does NOT work with GPG-encrypted wallets. The wallet MUST use standard blowfish encryption. + +### hyprlock caveat +- [fact] hyprlock uses `auth include login` in `/etc/pam.d/hyprlock`. The login PAM chain does NOT include kwallet PAM modules. Unlocking hyprlock will NOT re-open the wallet if it was closed. +- [mitigation] Typically the wallet stays open for the session duration. If the wallet is configured with `Leave Open=true` (in kwalletrc or kwalletmanager), it won't close automatically. + +### Password change caveat +- [fact] If the user's login password is changed (via `passwd`), the wallet password must be manually updated to match. PAM does not automatically synchronize wallet passwords on password change. + +## Relations +- related_to [[LUKS SDDM KWallet discovery]] +- related_to [[luks-sddm-kwallet-login-integration]] +- related_to [[LUKS SDDM KWallet documentation targets]] diff --git a/.memory/research/opencode-architecture.md b/.memory/research/opencode-architecture.md index ea07b92..e5ab588 100644 --- a/.memory/research/opencode-architecture.md +++ b/.memory/research/opencode-architecture.md @@ -1,3 +1,9 @@ +--- +title: opencode-architecture +type: note +permalink: dotfiles/research/opencode-architecture +--- + # OpenCode Architecture Research ## Overview @@ -103,4 +109,4 @@ Phases: CLARIFY → DISCOVER → CONSULT → PLAN → CRITIC-GATE → EXECUTE - **doc-coverage:** Validates canonical instruction file + symlinks; checks README + docs/* coverage - **git-workflow:** Step-by-step git commit, worktree, and PR creation procedures -- **work-decomposition:** Splits 3+ feature requests into independent workstreams with separate worktrees +- **work-decomposition:** Splits 3+ feature requests into independent workstreams with separate worktrees \ No newline at end of file diff --git a/.profile b/.profile index 4b38a7a..e69de29 100644 --- a/.profile +++ b/.profile @@ -1,2 +0,0 @@ - -. "$HOME/.local/bin/env"