Compare commits

..
1 Commits
Author SHA1 Message Date
tgrosinger 1b4bfa3e7e Waybar: add new memory widget 2026-09-15 13:38:26 -07:00
56 changed files with 2662 additions and 836 deletions

No files matched your search

-6
View File
@@ -6,12 +6,6 @@
# Python
*.pyc
# Secrets
home/.pi/agent/auth.json
home/.pi/agent/sessions
/home/.pi/agent/models-store.json
# dev-tickets CLI dependencies, installed by install-packages.sh (npm ci)
home/.local/lib/dev-tickets/node_modules/
home/.agents/skills/synced
+88 -5
View File
@@ -32,17 +32,86 @@ This needs no root: `cpu memory pids` are already delegated to the user manager
### The launcher
`dev-claude.fish` builds a launch prefix once and uses it at all four launch sites:
```fish
set -l launch /usr/bin/env claude
if command -q systemd-run
systemd-run --user --scope --quiet --collect --slice=claude.slice -- /usr/bin/env claude $argv
else
/usr/bin/env claude $argv
set launch systemd-run --user --scope --quiet --collect --slice=claude.slice -- /usr/bin/env claude
end
```
Because `systemd-run --scope` **execs** rather than forks, the resulting process tree is the same as running `claude` directly. The only difference is which cgroup it lands in.
Because `systemd-run --scope` **execs** rather than forks, the resulting process tree and command line are byte-identical to running `claude` directly. The only difference is which cgroup it lands in.
`/usr/bin/env` does the `PATH` lookup, so a fish function or alias named `claude` cannot shadow the real binary (and a future `claude` wrapper function cannot recurse into itself).
## Three non-obvious things
These are the parts that will look wrong later and get "cleaned up". Don't.
### 1. `/usr/bin/env` is load-bearing
`systemd-run` resolves its target through `PATH` and **rewrites `argv[0]` to an absolute path**:
```
$ systemd-run --user --scope --quiet -- argvprobe.sh
argv0=[/tmp/argvprobe.sh] # not "argvprobe.sh"
```
`~/.tmux.conf` sets `@resurrect-processes '"claude->dev-claude *"'`, and tmux-resurrect matches that with an **anchored** regex — `scripts/process_restore_helpers.sh`:
```bash
if [[ "$pane_full_command" =~ (^${match} ) ]] || [[ "$pane_full_command" =~ (^${match}$) ]]; then
```
So a bare `systemd-run … -- claude` makes the saved command `/home/tgrosinger/.local/bin/claude --session-id …`, which fails `^claude ` and **silently stops restoring Claude panes** — breaking the exact thing `dev-claude` exists to provide. There is no error; restore just quietly does nothing.
Interposing `env` fixes it, because `env` re-execs its target with `argv[0]` set to the bare name:
```
$ systemd-run --user --scope --quiet -- /usr/bin/env sleep 137
cmdline: [sleep 137] # bare argv[0], as if run directly
ppid: bash # systemd-run exec'd; no extra process in the tree
```
`env` also does the PATH lookup that `command claude` used to do here, so a fish function or alias named `claude` still cannot shadow the real binary.
### 2. `dev-claude` must not `exec`
This one bit once already: for months every Claude pane was saved, matched nothing, and restored nothing — silently.
tmux-resurrect's `ps` save strategy does not read the pane process. It reads the pane process's **children** (`save_command_strategies/ps.sh`):
```bash
ps -ao "ppid,args" | sed "s/^ *//" | grep "^${PANE_PID}" | cut -d' ' -f2-
```
`exec` makes Claude *become* the pane pid, so that grep returns Claude's own subprocesses instead of Claude. The saved `pane_full_command` came out as `socat UNIX-LISTEN:/tmp/claude-http-….sock …` — or empty, when nothing happened to be running — never `claude --session-id …`. Both fail `^claude `, so `@resurrect-processes` never fires.
Running Claude as a plain foreground child keeps fish at the pane pid, which is exactly where resurrect looks:
```
$ fish -c 'echo $fish_pid; /usr/bin/env sleep 3' # no exec
286 285 fish -c …
317 286 sleep 3
-> resurrect saves: [sleep 3]
$ fish -c 'echo $fish_pid; exec /usr/bin/env sleep 3'
328 285 sleep 3
-> resurrect saves: []
```
The cost is that the pane returns to a fish prompt when Claude exits rather than closing. That is the intended trade — a `dev` layout does not collapse when a session ends.
### 3. `command` cannot be used in the fallback
The natural fallback is `set -l launch command claude`. While `dev-claude` still used `exec`, fish rejected it outright:
```
fish: The expanded command is a keyword.
set -l launch command echo; exec $launch ok
^~~~~~^
```
`exec` will not accept an expansion that begins with a builtin. That specific constraint is gone with `exec`, but `/usr/bin/env claude` stays in both branches: it gives the same shadowing guarantee, and keeping the two branches identical means the saved command line does not depend on whether `systemd-run` was found.
## Limits, and why each one
@@ -99,6 +168,20 @@ Confirm a running session is actually inside the slice:
systemd-cgls --user-unit claude.slice
```
Confirm tmux-resurrect is unaffected — this is the string its `ps` save strategy reads. It must be non-empty, must name `claude` and not one of its subprocesses, and must show a **bare** `claude`, not an absolute path:
```bash
ps -ao ppid,args | grep "^$(tmux display -p '#{pane_pid}') "
# claude --session-id <uuid>
```
Then check what actually landed on disk, which is the thing restore reads:
```bash
grep -a claude ~/.local/share/tmux/resurrect/last | cut -f11
# :claude --session-id <uuid>
```
### Testing containment safely
Do **not** force an OOM inside `claude.slice` to test it. The kernel picks the largest consumer in the cgroup, which is very likely to be a real session rather than the test process. Use an unrelated top-level slice instead — note that systemd treats `-` as a hierarchy separator, so a name like `claude-test.slice` would nest *inside* `claude.slice` and hit the same problem:
-58
View File
@@ -1,58 +0,0 @@
---
name: blender-local
description: Build, edit, and render 3D scenes with the locally installed Blender on this Mac. Use when the user requests Blender work or an editable Blender scene.
---
# Local Blender
## Installed application
The verified executable is `/Applications/Blender.app/Contents/MacOS/Blender` (plural `Applications`, not `/Application/Blender`). It reported Blender 5.1.2 during the September 2026 pelican project. Check the executable if the installation changes; use this local app for Blender requests.
## Working workflow
Write scene-building scripts in the task's `work/` directory. Execute `bpy` scripts with Blender's bundled Python, not an ordinary Python interpreter:
```sh
/Applications/Blender.app/Contents/MacOS/Blender --background --python work/scene.py
```
For ordinary Python helpers outside Blender, use `uv run`. Set absolute output paths in the Blender script, create the destination directory, and save both the editable `.blend` and rendered PNG to the task's deliverable directory.
To edit a saved scene, call `bpy.ops.wm.open_mainfile(filepath=...)` before making changes. Only clear all objects when intentionally building a new scene. Prefer reusable functions or loading the existing `.blend` over executing fragments sliced out of earlier scripts.
This finalization pattern worked with the installed version; choose image dimensions and samples for the task:
```python
scene = bpy.context.scene
scene.render.engine = 'CYCLES'
scene.cycles.samples = 64
scene.cycles.use_denoising = True
scene.render.resolution_x = 1600
scene.render.resolution_y = 1200
scene.render.resolution_percentage = 100
scene.view_settings.view_transform = 'AgX'
scene.render.image_settings.file_format = 'PNG'
scene.render.filepath = str(output_dir / 'scene.png')
bpy.ops.wm.save_as_mainfile(filepath=str(output_dir / 'scene.blend'))
bpy.ops.render.render(write_still=True)
```
Use roughly 32–48 samples for previews and 64–96 for a polished still with denoising as starting points. Do not assume GPU acceleration is configured. Saving before rendering preserves the scene if rendering fails.
## Execution and diagnosis
- The first sandboxed launch in this project exited with code 139 before running the script and wrote `blender.crash.txt` in the system temporary directory. A retry through the approved unsandboxed execution mechanism succeeded. Treat this as an observed environment issue, not proof that every crash needs escalation. On a similar startup failure, inspect the output and request the applicable execution permission; if a permitted retry still fails, investigate rather than repeatedly escalating.
- A USD `Arch_ValidateAssumptions` warning accompanied that startup failure; it did not establish the root cause.
- `Material.use_nodes` and `World.use_nodes` emitted deprecation warnings in 5.1.2 but worked. They are expected to change in Blender 6; verify the installed API when upgrading.
- Background rendering can produce little output for tens of seconds. If execution returns a session ID, poll that session until completion instead of launching duplicate renders. Confirm the exit status and saved files.
## Modeling and visual lessons
- Cylinders aligned with `direction.to_track_quat('Z', 'Y')`, beveled curves, UV spheres, and custom meshes worked well for stylized scene construction. Smooth shading does not fix a faceted silhouette: give focal shapes enough geometry. Cap exposed curve ends or cover them with modeled joints.
- Inspect the rendered image after meaningful changes. Check the silhouette, grip and pedal contacts, floating parts, frame cropping, shadows, and whether background details are actually visible. A successfully saved render is not visual QA.
- Avoid overlapping coplanar surfaces. The retained studio floor hid the new beach and ocean; coincident surfaces produced black bands. Remove obsolete geometry and deliberately separate surface heights. For a box, calculate the top as center Z plus half its height.
- Frame an orthographic camera deliberately: an infinite ground plane fills the background without a natural horizon. A distant sky backdrop perpendicular to the horizontal viewing direction can provide a level horizon. Check projected positions of the sun, clouds, and distant props; adding them does not guarantee they appear in frame.
- For a substantial quality improvement, prioritize coherent composition, character anatomy, materials, and light over adding more objects. Preview warm key light, cooler fill, and rim light; avoid washed-out colors and unlit distant props. Keep decorative details from obscuring the subject.
Deliver the inspected render inline and link the editable `.blend` using absolute paths. Preserve earlier versions when making major revisions unless the user requests replacement.
+30 -22
View File
@@ -10,49 +10,57 @@ Help turn ideas into fully formed designs and specs through natural collaborativ
Start by understanding the current project context, then ask questions one at a time to refine the idea. Once you understand what you're building, present the design and get user approval.
Take no implementation action — no code, no scaffolding, no implementation skill — until the user has approved a design. This holds for every project, however simple: a todo list, a single-function utility, or a config change still gets a design, because simple projects are where unexamined assumptions waste the most work. For those, the design can be a few sentences.
<HARD-GATE>
Do NOT invoke any implementation skill, write any code, scaffold any project, or take any implementation action until you have presented a design and the user has approved it. This applies to EVERY project regardless of perceived simplicity.
</HARD-GATE>
## Anti-Pattern: "This Is Too Simple To Need A Design"
Every project goes through this process. A todo list, a single-function utility, a config change — all of them. "Simple" projects are where unexamined assumptions cause the most wasted work. The design can be short (a few sentences for truly simple projects), but you MUST present it and get approval.
## Checklist
Create a task for each item and complete them in order:
You MUST create a task for each of these items and complete them in order:
1. **Explore project context** — check files, docs, recent commits
2. **Ask clarifying questions** — one at a time, understand purpose/constraints/success criteria
3. **Propose 2-3 approaches** — with trade-offs and your recommendation
4. **Present design** — in sections scaled to their complexity, get user approval after each section
5. **Write spec to effort** — the body of an effort task in the vault, following the `dev-tickets` skill
6. **Spec self-review** — quick inline check for placeholders, contradictions, ambiguity, scope (see below)
7. **User reviews written spec** — ask user to review the effort before proceeding
8. **Transition to implementation** — hand off to `/to-tickets` to slice the effort into implementation tickets
3. **Ask clarifying questions** — one at a time, understand purpose/constraints/success criteria
4. **Propose 2-3 approaches** — with trade-offs and your recommendation
5. **Present design** — in sections scaled to their complexity, get user approval after each section
6. **Write design doc** — save to `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md` and commit
7. **Spec self-review** — quick inline check for placeholders, contradictions, ambiguity, scope (see below)
8. **User reviews written spec** — ask user to review the spec file before proceeding
9. **Transition to implementation** — invoke skills such as grill-with-docs or to-prd to create implementation plan
## Process Flow
```dot
digraph brainstorming {
"Explore project context" [shape=box];
"Visual questions ahead?" [shape=diamond];
"Ask clarifying questions" [shape=box];
"Propose 2-3 approaches" [shape=box];
"Present design sections" [shape=box];
"User approves design?" [shape=diamond];
"Write spec to effort" [shape=box];
"Write design doc" [shape=box];
"Spec self-review\n(fix inline)" [shape=box];
"User reviews spec?" [shape=diamond];
"Transition to implementation" [shape=doublecircle];
"Explore project context" -> "Ask clarifying questions";
"Explore project context" -> "Visual questions ahead?";
"Visual questions ahead?" -> "Ask clarifying questions" [label="no"];
"Ask clarifying questions" -> "Propose 2-3 approaches";
"Propose 2-3 approaches" -> "Present design sections";
"Present design sections" -> "User approves design?";
"User approves design?" -> "Present design sections" [label="no, revise"];
"User approves design?" -> "Write spec to effort" [label="yes"];
"Write spec to effort" -> "Spec self-review\n(fix inline)";
"User approves design?" -> "Write design doc" [label="yes"];
"Write design doc" -> "Spec self-review\n(fix inline)";
"Spec self-review\n(fix inline)" -> "User reviews spec?";
"User reviews spec?" -> "Write spec to effort" [label="changes requested"];
"User reviews spec?" -> "Write design doc" [label="changes requested"];
"User reviews spec?" -> "Transition to implementation" [label="approved"];
}
```
**The terminal state is an approved spec in an effort task.** Do NOT invoke any other implementation skill. The only next step after brainstorming is `/to-tickets`.
**The terminal state is writing a plan.** Do NOT invoke frontend-design, mcp-builder, or any other implementation skill. The ONLY skills you invoke after brainstorming are grill-with-docs or to-prd.
## The Process
@@ -97,13 +105,13 @@ digraph brainstorming {
**Documentation:**
- Write the validated design (spec) as the body of an effort task in the vault. The `dev-tickets` skill owns where it goes, its frontmatter, and the `ticket` commands that write it.
- If `/wayfinder` already charted this effort, the effort task exists and its body is the map: keep `## Notes` and `## Decisions so far`, and replace `## Destination` with the spec.
- Otherwise create the effort task. It carries no actor tag; only tickets do.
- Write the validated design (spec) to `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md`
- (User preferences for spec location override this default)
- Use elements-of-style:writing-clearly-and-concisely skill if available
- Commit the design document to git
**Spec Self-Review:**
After writing the spec, look at it with fresh eyes:
After writing the spec document, look at it with fresh eyes:
1. **Placeholder scan:** Any "TBD", "TODO", incomplete sections, or vague requirements? Fix them.
2. **Internal consistency:** Do any sections contradict each other? Does the architecture match the feature descriptions?
@@ -115,14 +123,14 @@ Fix any issues inline. No need to re-review — just fix and move on.
**User Review Gate:**
After the spec review loop passes, ask the user to review the written spec before proceeding:
> "Spec written to the effort `<effort title>`. Please review it and let me know if you want to make any changes before we break it into tickets."
> "Spec written and committed to `<path>`. Please review it and let me know if you want to make any changes before we start writing out the implementation plan."
Wait for the user's response. If they request changes, make them and re-run the spec review loop. Only proceed once the user approves.
**Implementation:**
- Ask the user to run `/to-tickets <effort title>` to break the spec into implementation tickets
- Do NOT invoke any other skill. `/to-tickets` is the next step.
- Invoke the grill-with-docs skill to create a detailed implementation plan
- Do NOT invoke any other skill. grill-with-docs is the next step.
## Key Principles
-1
View File
@@ -1 +0,0 @@
/home/tgrosinger/obsidian/team-vaults/obsidian-team/Development/Context/Agent Skills/dev-tickets-obsidian
+1 -3
View File
@@ -1,12 +1,10 @@
---
name: dev-tickets
description: Storage model for development tickets, specs, and planning maps in the personal TaskNotes tracker, read and written with the `ticket` CLI. Use when creating an effort or spec, writing implementation or decision tickets, finding the frontier, or claiming, annotating, and closing a ticket in that personal tracker — and whenever /to-spec, /to-tickets, /wayfinder, or an implementor reads or writes records there. For records in Obsidian Team or Obsidian Community, use dev-tickets-obsidian instead. Choose by the authoritative record's destination, not the repository or project name; if the destination is unclear, ask before writing.
description: Storage model for development tickets, specs, and planning maps, which live in the Obsidian vault as TaskNotes tasks and are read and written with the `ticket` CLI. Use when creating an effort or spec, writing implementation or decision tickets, finding the frontier, or claiming, annotating, and closing a ticket — and whenever /to-spec, /to-tickets, /wayfinder, or an implementor reads or writes them.
---
# Dev tickets
Use this skill for the personal TaskNotes tracker configured for the `ticket` CLI. For records in Obsidian Team or Obsidian Community, use `dev-tickets-obsidian` instead. Select by the authoritative record’s destination, not the repository or project name. Do not reconfigure `ticket` to switch between these storage models. If the destination is unclear, ask before writing.
Tickets, specs, and planning maps live in the Obsidian vault as TaskNotes tasks. They are read and written with **`ticket`**, a file-based CLI that works on the markdown directly — no running Obsidian, no HTTP API — so it behaves the same on every host. This skill owns the storage model: the shape on disk, the metadata, and the verbs that read and write it. The skills that produce tickets (`/to-spec`, `/to-tickets`, `/wayfinder`) own their own process and defer here for everything below.
**Where the vault is** is what `ticket vault` prints. It is configured once per host, and the skill never names a path:
-1
View File
@@ -1 +0,0 @@
../../../mattpocock-skills/skills/engineering/implement-spec/
+121
View File
@@ -0,0 +1,121 @@
---
name: magpie-review
description: Run a multi-AI adversarial code review using the `magpie` CLI. Multiple AI models independently review the changes, debate findings, and a verifier audits each issue against the actual code. Use whenever the user asks for a "magpie review", a "multi-AI review", an "adversarial review", a "second opinion review", or wants magpie to look at local uncommitted changes, the current branch, or a GitHub PR. Also use when the user wants to `magpie discuss` a topic or do a whole-repo review.
---
# magpie-review
Wraps the `magpie` CLI to run adversarial multi-AI code reviews. Magpie spawns several reviewer models (Claude Code, Codex, Gemini, etc.) that independently review a change, debate across rounds, then a verifier audits each reported issue against the actual code.
## When to pick which mode
Magpie supports three review targets — pick based on what the user is reviewing:
| User's intent | Command |
|---|---|
| Review work I haven't committed yet (staged + unstaged) | `magpie review --local` |
| Review the commits on my current branch vs a base | `magpie review --branch [base]` (base defaults to `main`) |
| Review a GitHub PR | `magpie review <pr-number>` or `magpie review <pr-url>` |
| Review specific files only | `magpie review --files <path> [path...]` |
| Review the entire repository | `magpie review --repo` |
| Discuss a topic / design question | `magpie discuss "<topic>"` or `magpie discuss <path-to-file.md>` |
If the user is ambiguous (e.g. "review my changes"), check `git status` and `git log @{u}..HEAD` to figure out whether they mean uncommitted, committed-but-unpushed, or already-pushed work — then pick the matching mode rather than guessing.
## Running a review
Always run `magpie` from inside the target repo's working tree. For PR mode it uses the `origin` remote to find the repo by default.
### Common flags
These apply to both `review` and `discuss` unless noted:
- `-i, --interactive` — Pause between turns for Q&A. Use when the user wants to drive the review themselves.
- `-a, --all` — Use every configured reviewer without an interactive picker. Good for non-interactive/batch runs.
- `--reviewers <ids>` — Comma-separated reviewer IDs (e.g. `claude-code,gemini-cli`) when you want a specific subset.
- `-r, --rounds <n>` — Cap the debate rounds (default 5).
- `--no-converge` — Disable early-stop on consensus. Use when you want the full debate even if reviewers agree quickly.
- `-o, --output <file>` and `-f, --format <markdown|json>` — Save results to a file.
- `--fail-fast` — Abort the whole flow if any reviewer fails. Default is resilient (continues with surviving reviewers). Use fail-fast when debugging provider/auth issues or when the user wants a guarantee every reviewer participated.
- `--plan-only` — Generate the review plan without running reviewers. Useful for a quick preview of what magpie *would* do.
### `review`-only flags worth knowing
- `--skip-context` — Skip the context-gathering phase (call chains, related PRs). Faster, less informed.
- `--no-post` — Skip the post-debate GitHub comment-posting flow. Use in non-interactive contexts where you just want the review output, not the interactive post-each-issue loop.
- `--no-conclusion` — Skip the final summarizer. Useful for bot/CI use.
- `--git-remote <remote>` — Override the remote used for PR-URL detection (default `origin`).
- `--reanalyze` — Bypass the analyzer cache and re-analyze from scratch.
### Repo-mode flags (with `--repo`)
- `--path <subdir>` — Limit the repo review to a subdirectory.
- `--ignore <patterns...>` — Skip matching paths.
- `--quick` — Architecture overview only.
- `--deep` — Full analysis, no prompts.
- `--list-sessions` / `--session <id>` / `--export <file>` — Manage long-running repo review sessions (they persist so you can pause and resume).
## Interactive vs non-interactive
Magpie's default flow includes interactive prompts (reviewer selection, per-issue post/edit/skip after the debate). When you (Claude) are invoking magpie programmatically on the user's behalf:
- Prefer `-a` (or `--reviewers`) to skip the reviewer-selection prompt.
- Prefer `--no-post` to skip the per-issue posting loop — the user can still read the review output.
- If you want a clean machine-readable result, add `-f json -o <file>`.
When the user wants to drive the review themselves, hand the command back to them to run (e.g. via `! magpie review ...`) so they get the interactive UX rather than running it through a tool call.
## Running it as a long task (it takes minutes)
A full review runs several models across multiple debate rounds, so it takes minutes. Run it as a background `Bash` task with `run_in_background: true` and save the output (`-f markdown -o <file>`). The background task auto-notifies you when it completes — that completion notification is all you need; read the saved output file then.
- **Do not add a separate `Monitor` on the same output file.** The background task already notifies on completion, so a monitor watching the same file is redundant. Only add a `Monitor` if you genuinely need streamed interim progress, and even then it is usually unnecessary for a fire-and-forget review.
- **Never copy the output path by hand.** Pass the same explicit `-o <file>` path you chose (e.g. `/tmp/magpie-review.md`) to your follow-up `Read` — don't transcribe the long auto-generated task-output path from the completion notification, which is easy to typo.
- **Don't suppress stderr** (`2>/dev/null`) on magpie or on any watcher command. If something fails — bad path, auth error, missing reviewer — you want to see why, not a bare non-zero exit. Use `2>&1 | tee <log>` if you want both a saved log and visible errors.
## Examples
**User: "Have magpie look at what I'm working on right now."**
They likely mean uncommitted work. Run:
```
magpie review --local
```
**User: "Get a magpie review on this branch before I push."**
Current branch vs main:
```
magpie review --branch
```
**User: "Run magpie on PR 4521."**
```
magpie review 4521
```
**User: "Use magpie to review just the changes to `src/auth/`."**
Pick the files mode:
```
magpie review --files src/auth/login.ts src/auth/session.ts
```
**User: "Get a fast magpie sanity check on PR 4521 — I just want the output, don't post anything."**
```
magpie review 4521 -a --no-post --skip-context
```
**User: "Have magpie debate whether we should adopt tRPC."**
```
magpie discuss "Should we adopt tRPC for our internal APIs?"
```
## Configuration notes
- Magpie reads `~/.magpie/config.yaml` for providers, reviewers, analyzer, summarizer, and the context-gatherer config.
- CLI providers (`claude-code`, `codex-cli`, `gemini-cli`, `qwen-code`, `opencode-cli`) use the user's existing subscriptions/logins — no API keys needed and they're the recommended choice.
- If the user hasn't run `magpie init` yet, suggest `magpie init` (interactive) or `magpie init -y` (defaults) before the first review.
- If `magpie` is not on PATH, the project at `/home/tgrosinger/code/magpie` may need `npm install && npm run build && npm link` from its root.
## When *not* to use this skill
- The user is asking how magpie itself is implemented or wants to modify magpie's source — that's a normal code task in the magpie repo, not an invocation of this skill.
- The user wants a single-model review (just Claude reviewing the diff). Use the built-in `/code-review` skill instead.
+1
View File
@@ -0,0 +1 @@
../../../mattpocock-skills/skills/engineering/resolving-merge-conflicts
@@ -1,14 +0,0 @@
---
name: resolving-merge-conflicts
description: "Use when you need to resolve an in-progress git merge/rebase conflict."
---
1. **See the current state** of the merge/rebase. Check git history, and the conflicting files.
2. **Find the primary sources** for each conflict. Understand deeply why each change was made, and what the original intent was. Read the commit messages, check the PRs, check original issues/tickets.
3. **Resolve each hunk.** Preserve both intents where possible. Where incompatible, pick the one matching the merge's stated goal and note the trade-off. Do **not** invent new behaviour. Always resolve; never `--abort`.
4. Discover the project's **automated checks** and run them, typically typecheck, then tests, then format. Fix anything the merge broke.
5. **Finish the merge/rebase.** Stage everything and commit. If rebasing, continue the rebase process until all commits are rebased.
@@ -1,3 +0,0 @@
interface:
display_name: "Resolving Merge Conflicts"
short_description: "Resolve merge and rebase conflicts"
@@ -1,66 +0,0 @@
---
name: traefik-expose
description: Make a service on the voyager reachable at https://NAME.i.grosinger.net through Traefik, or remove it. Use when asked to expose, register, route, or publish a dev server, host process, or docker container on an internal hostname, or to unexpose/deregister one.
---
> [!info] This skill only applies to the host `voyager`
> This skill may be synced to other hosts, but it only applies to `voyager`. If you are running on a different host and need to expose a service to an internal or external hostname, stop and ask for guidance from the user.
# traefik-expose — put a service on NAME.i.grosinger.net
Traefik on this host (`/tachi/docker`) serves `*.i.grosinger.net` on its `internal` entrypoint. That entrypoint is the default and already carries the wildcard TLS certificate and the home-only IP allowlist, and Blocky resolves every `*.i.grosinger.net` name to this host. So registering a service is only a routing rule and a target; there is no DNS, certificate, or middleware step.
Pick the branch by where the service runs.
## Host process (not in a container)
Register with the script in the docker repo:
```sh
/tachi/docker/traefik/expose NAME PORT # https://NAME.i.grosinger.net -> host:PORT
/tachi/docker/traefik/expose -l # list
/tachi/docker/traefik/expose -d NAME # remove
```
It writes one file to `traefik/dynamic.d/`, which Traefik watches, so the route is live within seconds and needs no restart. The file is gitignored.
The process must listen on `0.0.0.0` or on `172.19.0.1`. Traefik connects from inside its container network and cannot reach a listener bound to `127.0.0.1`, which most dev servers default to; pass the tool's host flag (`--host 0.0.0.0` or equivalent).
## Docker container
Join the container to the `docker_traefik` network and add labels. From a compose file outside `/tachi/docker`, declare the network as external:
```yaml
services:
myapp:
networks: [traefik]
labels:
- "traefik.enable=true"
- "traefik.http.routers.myapp.rule=Host(`myapp.i.grosinger.net`)"
- "traefik.http.services.myapp.loadbalancer.server.port=3000"
networks:
traefik:
external: true
name: docker_traefik
```
Inside `/tachi/docker/docker-compose.yaml` the network is simply `traefik`. Traefik ignores containers without `traefik.enable=true`. Always set the port label: it is the port the app listens on inside the container, not a published one, and no `ports:` mapping is needed. Removing the labels or the container removes the route.
## Verify
```sh
curl -sk -o /dev/null -w '%{http_code}\n' https://NAME.i.grosinger.net/
```
- **200-ish**: done.
- **502**: Traefik has the route but cannot reach the target. Host process: check the bind address with `ss -ltnp | grep PORT`. Container: check the port label matches what the app listens on and the container is on `docker_traefik`.
- **404**: Traefik has no router for that host. Ask the dashboard API, which needs no docker socket:
```sh
curl -sk https://traefik.i.grosinger.net/api/http/routers/NAME@file # host process
curl -sk https://traefik.i.grosinger.net/api/http/routers/NAME@docker # container
```
## Public exposure is a different task
Everything above is reachable only from the LAN and Tailscale. Making a service internet-facing means a real `grosinger.net` name, an explicit `traefik.http.routers.NAME.entrypoints=websecure` label, and a deliberate decision by the user. Do not add `websecure` when asked for an internal hostname.
-1
View File
@@ -1 +0,0 @@
/home/tgrosinger/obsidian/team-vaults/obsidian-team/Development/Context/Agent Skills/wayfinder-obsidian
@@ -17,9 +17,9 @@
set -euo pipefail
STATION_ID=173994
API_KEY=b29d10d0-6e40-44a5-869d-f7af76072b6b
API_KEY=6bff2f89-84ab-463c-886e-fc0f443da4cf
API_BASE=https://swd.weatherflow.com/swd/rest
BUILD=181
BUILD=169
# Everything below the high/low is an integral, and an integral fails quietly: a
# wrong high looks wrong, a wrong degree-day total looks like a number. So this
@@ -56,17 +56,6 @@ MAX_GAP_SECONDS=3600
ORIGIN=https://tempestwx.com
USER_AGENT='Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0'
# Since build ~181 the API also wants `token`, a Firebase ID token. The web app
# gets one from firebase.auth().signInAnonymously() on public station pages; this
# is the REST form of that call, with the `apiKey` from the Firebase config in the
# tempestwx.com main.js bundle. The key is referrer-restricted, so the Referer is
# required — without it Google answers 403 API_KEY_HTTP_REFERRER_BLOCKED. Tokens
# last an hour, far longer than one run, so a fresh one per run is enough.
#
# Also reaches identitytoolkit.googleapis.com, which needs the same squid.conf
# allowance as swd.weatherflow.com.
FIREBASE_API_KEY=AIzaSyA8aLVHWe7TVmctOXXVXYTl4pnzTgUydG4
if [ $# -gt 1 ]; then
echo 'usage: weather-day [YYYY-MM-DD] (default: yesterday)' >&2
exit 2
@@ -107,7 +96,6 @@ tempest_get() {
-H "Origin: ${ORIGIN}" \
--data-urlencode "api_key=${API_KEY}" \
--data-urlencode "build=${BUILD}" \
--data-urlencode "token=${TOKEN}" \
"${@:2}")
code=${resp##*$'\n'}
json=${resp%$'\n'*}
@@ -120,18 +108,6 @@ tempest_get() {
printf '%s' "$json"
}
signup=$(curl -sS -X POST \
"https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=${FIREBASE_API_KEY}" \
-H 'Content-Type: application/json' \
-H "Referer: ${ORIGIN}/" \
-d '{"returnSecureToken":true}')
TOKEN=$(printf '%s' "$signup" | jq -r '.idToken // empty')
if [ -z "$TOKEN" ]; then
echo "weather-day: anonymous Firebase sign-in failed" >&2
echo " $(printf '%s' "$signup" | jq -c '.error // .' 2>/dev/null || printf '%s' "$signup")" >&2
exit 1
fi
# A station has one ST (Tempest) device and usually an HB (hub) alongside it; only
# the ST reports weather.
locations=$(tempest_get "locations/${STATION_ID}" --data-urlencode 'include_arbitrary_locations=true')
-91
View File
@@ -1,91 +0,0 @@
## Critical rules
Never delete files outside your own temp directory, and never attempt to circumvent the restrictions on deleting files. Cleaning up scratch files under /tmp/claude-1000 with a plain rm/rmdir to an absolute path is allowed; anything else you must ask me to delete manually.
```sh
# Allowed
rm /tmp/claude-1000/file
rm -rf -- /tmp/claude-1000/directory
## NOT Allowed
rm $TMPDIR/file
rm /tmp/claude-1000/*.log
rm -rf /tmp/claude-1000/../other
```
## Issue tracker and tickets
Tickets, specs, and wayfinder maps live in my Obsidian vault as TaskNotes tasks. The `dev-tickets` skill owns that model — invoke it whenever a skill or I reference a ticket, spec, or effort.
- Update the ticket's status as the work proceeds, and log hurdles and design changes to its `## Notes` while they happen.
- When implementation of a ticket materially deviates from what was written, note the changes in an "As Built" section at the bottom.
- A few repos still have a `.scratch/` directory from the previous system. Those efforts stay where they are; new ones use the vault.
## Memories
Do not use your memories function to store learned information. Instead, when you want to remember something, ask if you could add it to the `CLAUDE.local.md` in the repo. For information that is globally relevant, ask to write it to the global `CLAUDE.md`.
## Communication
- Open with the substance of the answer, not with agreement or praise for the question.
- When you got something wrong, state the correction in a sentence and move on.
- No emojis.
## Commands and System Interactions
- Claude will likely always be running in a tmux session.
- Claude is generally run from a sandbox and will not have permission to create new panes or send tmux commands.
- I generally do not run shell commands in claude with the exclamation point syntax. Instead, commands are run in a separate tmux pane.
## When writing code
Before writing any code, stop at the first rung that holds:
1. Does this need to be built at all? (YAGNI)
2. Does it already exist in this codebase? Reuse the helper, util, or pattern that's already here, don't re-write it.
3. Does the standard library already do this? Use it.
4. Does a native platform feature cover it? Use it.
5. Does an already-installed dependency solve it? Use it.
6. Can this be one line? Make it one line.
7. Only then: write the minimum code that works.
The ladder runs after you understand the problem, not instead of it: read the task and the code it touches, trace the real flow end to end, then climb.
Bug fix = root cause, not symptom: a report names a symptom. Grep every caller of the function you touch and fix the shared function once — one guard there is a smaller diff than one per caller, and patching only the path the ticket names leaves a sibling caller still broken.
Rules:
- No abstractions that weren't explicitly requested.
- No new dependency if it can be avoided.
- No boilerplate nobody asked for.
- Deletion over addition. Boring over clever. Fewest files possible.
- Shortest working diff wins, but only once you understand the problem. The smallest change in the wrong place is a second bug.
- Question complex requests: "Do you actually need X, or does Y cover it?"
- Pick the edge-case-correct option when two stdlib approaches are the same size.
- Avoid over commenting. Comments in code should be added where they explain something non-obvious, or of high importance.
The bias toward small diffs does not apply to these, which get full effort even when that makes the change larger: understanding the problem (read it fully and trace the real flow before picking a rung; a small diff you don't understand often lands in the wrong place), input validation at trust boundaries, error handling that prevents data loss, security, accessibility, the calibration real hardware needs (the platform is never the spec ideal, a clock drifts, a sensor reads off), anything explicitly requested. Trivial one-liners need no test.
## When writing markdown
- Do not use hard line breaks in prose to meet a target column width. Long lines are okay and editors will soft wrap.
- The exception to this is git commits, which should shoot for 60 columns in the summary, and 80 columns in the body.
## Finalizing
- Never add yourself as a co-author when committing changes.
## Sandbox artifacts in `git status` (not real files)
Claude Code's Bash sandbox blocks reads of config files that could alter agent behavior. It enforces this by bind-mounting `/dev/null` over each path, so the masked entries show up in the repo root as **character devices** (`crw-rw-rw-`, device `1,3`, owned by `nobody`/65534, size 0) rather than regular files:
.bashrc .zshrc .bash_profile .profile .zprofile .gitconfig .gitmodules .ripgreprc .mcp.json .idea .vscode .claude/{settings.json,skills,hooks,launch.json,routines,workflows,...}
They are created at session start, so a repo that was clean can show a dozen untracked dotfiles a moment later. They contain nothing, they are not mine, and they vanish outside the sandbox. Nothing to delete or gitignore.
**The one practical consequence:** `git add -A` and `git add .` don't just include noise — they **fail outright**:
error: .bash_profile: can only add regular files, symbolic links or git-directories
fatal: adding files failed
Git refuses to stage a device node. So in a sandboxed session, stage by explicit path (`git add README.md docs/`) rather than `-A`/`.`. If `git add -A` fails with "can only add regular files", this is why — it is not repo corruption.
+8 -8
View File
@@ -1,8 +1,7 @@
{
"attribution": {
"commit": "",
"pr": "",
"sessionUrl": false
"pr": ""
},
"permissions": {
"allow": [
@@ -31,7 +30,7 @@
],
"defaultMode": "auto"
},
"model": "opus[1m]",
"model": "claude-opus-4-8",
"disableClaudeAiConnectors": true,
"hooks": {
"PostToolUse": [
@@ -103,7 +102,6 @@
"allowUnsandboxedCommands": false,
"network": {
"allowedDomains": [
"*.i.grosinger.net",
"github.com",
"*.github.com",
"*.githubusercontent.com",
@@ -122,16 +120,19 @@
"~/.local/share/pnpm",
"~/.cache/pnpm",
"~/Documents/Atrium",
"/tachi/atrium"
"/tachi/docker/atribot/vault"
],
"denyRead": [
"~/.ssh",
"~/.config/Signal",
"~/obsidian/obsidian/ansible/variables",
"~/Documents",
"/tachi/backups",
"/tachi/documents",
"/tachi/docker"
],
"allowRead": [
"~/Documents/Atrium",
"/tachi/docker/atribot/vault"
]
},
"excludedCommands": [
@@ -139,7 +140,6 @@
"brew *"
]
},
"feedbackDrafts": "off",
"spinnerVerbs": {
"mode": "replace",
"verbs": [
@@ -155,7 +155,7 @@
"prefersReducedMotion": true,
"autoMemoryEnabled": true,
"autoDreamEnabled": true,
"theme": "auto",
"theme": "light",
"editorMode": "vim",
"remoteControlAtStartup": false,
"agentPushNotifEnabled": true,
+1 -2
View File
@@ -1,2 +1 @@
--theme-light="Catppuccin Latte"
--theme-dark="Catppuccin Mocha"
--theme="Catppuccin Latte"
File diff suppressed because it is too large. Load diff
+37 -1
View File
@@ -2,7 +2,7 @@
#* Name of a btop++/bpytop/bashtop formatted ".theme" file, "Default" and "TTY" for builtin themes.
#* Themes should be placed in "../share/btop/themes" relative to binary or "$HOME/.config/btop/themes"
color_theme = "/home/tgrosinger/.config/btop/themes/current.theme"
color_theme = "/home/tgrosinger/.config/btop/themes/catppuccin_latte.theme"
#* If the theme set background should be shown, set to False if you want terminal background transparency.
theme_background = true
@@ -48,6 +48,9 @@ graph_symbol = "braille"
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
graph_symbol_cpu = "default"
# Graph symbol to use for graphs in gpu box, "default", "braille", "block" or "tty".
graph_symbol_gpu = "default"
# Graph symbol to use for graphs in cpu box, "default", "braille", "block" or "tty".
graph_symbol_mem = "default"
@@ -114,6 +117,9 @@ cpu_graph_upper = "Auto"
#* Select from a list of detected attributes from the options menu.
cpu_graph_lower = "Auto"
#* If gpu info should be shown in the cpu box. Available values = "Auto", "On" and "Off".
show_gpu_info = "Auto"
#* Toggles if the lower CPU graph should be inverted.
cpu_invert_lower = true
@@ -248,3 +254,33 @@ log_level = "WARNING"
#* Automatically save current settings to config file on exit.
save_config_on_exit = true
#* Measure PCIe throughput on NVIDIA cards, may impact performance on certain cards.
nvml_measure_pcie_speeds = true
#* Measure PCIe throughput on AMD cards, may impact performance on certain cards.
rsmi_measure_pcie_speeds = true
#* Horizontally mirror the GPU graph.
gpu_mirror_graph = true
#* Set which GPU vendors to show. Available values are "nvidia amd intel apple"
shown_gpus = "nvidia amd intel"
#* Custom gpu0 model name, empty string to disable.
custom_gpu_name0 = ""
#* Custom gpu1 model name, empty string to disable.
custom_gpu_name1 = ""
#* Custom gpu2 model name, empty string to disable.
custom_gpu_name2 = ""
#* Custom gpu3 model name, empty string to disable.
custom_gpu_name3 = ""
#* Custom gpu4 model name, empty string to disable.
custom_gpu_name4 = ""
#* Custom gpu5 model name, empty string to disable.
custom_gpu_name5 = ""
@@ -1,83 +0,0 @@
# Main background, empty for terminal default, need to be empty if you want transparent background
theme[main_bg]="#1e1e2e"
# Main text color
theme[main_fg]="#cdd6f4"
# Title color for boxes
theme[title]="#cdd6f4"
# Highlight color for keyboard shortcuts
theme[hi_fg]="#89b4fa"
# Background color of selected item in processes box
theme[selected_bg]="#45475a"
# Foreground color of selected item in processes box
theme[selected_fg]="#89b4fa"
# Color of inactive/disabled text
theme[inactive_fg]="#7f849c"
# Color of text appearing on top of graphs, i.e uptime and current network graph scaling
theme[graph_text]="#f5e0dc"
# Background color of the percentage meters
theme[meter_bg]="#45475a"
# Misc colors for processes box including mini cpu graphs, details memory graph and details status text
theme[proc_misc]="#f5e0dc"
# CPU, Memory, Network, Proc box outline colors
theme[cpu_box]="#cba6f7" #Mauve
theme[mem_box]="#a6e3a1" #Green
theme[net_box]="#eba0ac" #Maroon
theme[proc_box]="#89b4fa" #Blue
# Box divider line and small boxes line color
theme[div_line]="#6c7086"
# Temperature graph color (Green -> Yellow -> Red)
theme[temp_start]="#a6e3a1"
theme[temp_mid]="#f9e2af"
theme[temp_end]="#f38ba8"
# CPU graph colors (Teal -> Lavender)
theme[cpu_start]="#94e2d5"
theme[cpu_mid]="#74c7ec"
theme[cpu_end]="#b4befe"
# Mem/Disk free meter (Mauve -> Lavender -> Blue)
theme[free_start]="#cba6f7"
theme[free_mid]="#b4befe"
theme[free_end]="#89b4fa"
# Mem/Disk cached meter (Sapphire -> Lavender)
theme[cached_start]="#74c7ec"
theme[cached_mid]="#89b4fa"
theme[cached_end]="#b4befe"
# Mem/Disk available meter (Peach -> Red)
theme[available_start]="#fab387"
theme[available_mid]="#eba0ac"
theme[available_end]="#f38ba8"
# Mem/Disk used meter (Green -> Sky)
theme[used_start]="#a6e3a1"
theme[used_mid]="#94e2d5"
theme[used_end]="#89dceb"
# Download graph colors (Peach -> Red)
theme[download_start]="#fab387"
theme[download_mid]="#eba0ac"
theme[download_end]="#f38ba8"
# Upload graph colors (Green -> Sky)
theme[upload_start]="#a6e3a1"
theme[upload_mid]="#94e2d5"
theme[upload_end]="#89dceb"
# Process box color gradient for threads, mem and cpu usage (Sapphire -> Mauve)
theme[process_start]="#74c7ec"
theme[process_mid]="#b4befe"
theme[process_end]="#cba6f7"
-22
View File
@@ -1,22 +0,0 @@
#
# Catppuccin Mocha, layered on dunstrc by waybar/theme.sh in dark mode
# https://github.com/catppuccin/dunst/blob/main/themes/mocha.conf
#
[global]
frame_color = "#89b4fa"
separator_color= frame
highlight = "#89b4fa"
[urgency_low]
background = "#1e1e2e"
foreground = "#cdd6f4"
[urgency_normal]
background = "#1e1e2e"
foreground = "#cdd6f4"
[urgency_critical]
background = "#1e1e2e"
foreground = "#cdd6f4"
frame_color = "#fab387"
@@ -0,0 +1,48 @@
# This file was created by fish when upgrading to version 4.3, to migrate
# theme variables from universal to global scope.
# Don't edit this file, as it will be written by the web-config tool (`fish_config`).
# To customize your theme, delete this file and see
# help interactive#syntax-highlighting
# or
# man fish-interactive | less +/^SYNTAX.HIGHLIGHTING
# for appropriate commands to add to ~/.config/fish/config.fish instead.
# See also the release notes for fish 4.3.0 (run `help relnotes`).
set --global fish_color_autosuggestion 9ca0b0
set --global fish_color_cancel d20f39
set --global fish_color_command 1e66f5
set --global fish_color_comment 8c8fa1
set --global fish_color_cwd df8e1d
set --global fish_color_cwd_root red
set --global fish_color_end fe640b
set --global fish_color_error d20f39
set --global fish_color_escape e64553
set --global fish_color_gray 9ca0b0
set --global fish_color_history_current --bold
set --global fish_color_host 1e66f5
set --global fish_color_host_remote 40a02b
set --global fish_color_keyword 8839ef
set --global fish_color_normal 4c4f69
set --global fish_color_operator ea76cb
set --global fish_color_option 40a02b
set --global fish_color_param dd7878
set --global fish_color_quote 40a02b
set --global fish_color_redirection ea76cb
set --global fish_color_search_match --background=ccd0da
set --global fish_color_selection --background=ccd0da
set --global fish_color_status d20f39
set --global fish_color_user 179299
set --global fish_color_valid_path --underline
set --global fish_pager_color_background
set --global fish_pager_color_completion 4c4f69
set --global fish_pager_color_description 9ca0b0
set --global fish_pager_color_prefix ea76cb
set --global fish_pager_color_progress 9ca0b0
set --global fish_pager_color_secondary_background
set --global fish_pager_color_secondary_completion
set --global fish_pager_color_secondary_description
set --global fish_pager_color_secondary_prefix
set --global fish_pager_color_selected_background
set --global fish_pager_color_selected_completion
set --global fish_pager_color_selected_description
set --global fish_pager_color_selected_prefix
+1 -4
View File
@@ -13,10 +13,6 @@ if status is-interactive
# https://fishshell.com/docs/current/cmds/fish_greeting.html
set -g fish_greeting
# Has [light] (latte) and [dark] (mocha) sections; fish picks one from the
# terminal's color scheme and switches live.
fish_config theme choose catppuccin-mocha
if command -q brew
brew shellenv | source
else if test -x /home/linuxbrew/.linuxbrew/bin/brew
@@ -31,6 +27,7 @@ if status is-interactive
# Aliases
alias vim="nvim"
alias lg="lazygit"
alias la="eza --long --header --git --group --time-style long-iso -a"
alias record='wf-recorder -g "$(slurp)"'
alias claer="clear"
-12
View File
@@ -1,12 +0,0 @@
function dev-app -d "Run a checkout's Obsidian dev app on voyager, shown here through waypipe"
# No argument: master's checkout; otherwise the obsidian worktree of that name.
set -l checkout /tachi/code/obsidian/obsidian
if test -n "$argv[1]"
set checkout /tachi/code/obsidian/obsidian.worktrees/$argv[1]
end
# waypipe execs the remote command directly, and ssh flattens it into one
# string for voyager's shell, so a shell builtin like cd or && can't be used.
# env -C sets the working directory instead. ods exec app starts Electron as
# a Wayland client with the checkout's own user data.
waypipe --compress zstd ssh voyager env -C $checkout ods exec app
end
+49 -6
View File
@@ -1,13 +1,56 @@
function dev-claude -d "Start Claude inside the memory-capped claude.slice"
function dev-claude -d "Start Claude with a durable session id so tmux-resurrect can restore the conversation"
# tmux-resurrect saves each pane's command line verbatim and replays it on
# restore. Pinning the session id at launch is what lets a restored pane
# rejoin its exact conversation; cwd alone can't disambiguate, since several
# Claude sessions often share one worktree.
# Run Claude inside a transient scope in claude.slice so a runaway subprocess
# tree hits that slice's memory cap and is killed there, instead of thrashing
# the whole machine into a lockup. See ~/.dotfiles/docs/claude-resource-limits.md
#
# /usr/bin/env does the PATH lookup, so a fish function or alias named claude
# can't shadow the real binary.
# The /usr/bin/env shim is load-bearing, in two ways:
# 1. systemd-run resolves its target through PATH and rewrites argv[0] to an
# absolute path. tmux-resurrect matches panes with an anchored "^claude "
# regex, so without the shim the saved command becomes an absolute path,
# stops matching, and pane restore silently dies. env re-execs with argv[0]
# as a bare "claude", keeping the saved command byte-identical.
# 2. env does the PATH lookup that "command" would do here, so a fish
# function or alias named claude still can't shadow the real binary.
set -l launch /usr/bin/env claude
if command -q systemd-run
systemd-run --user --scope --quiet --collect --slice=claude.slice -- /usr/bin/env claude $argv
else
/usr/bin/env claude $argv
set launch systemd-run --user --scope --quiet --collect --slice=claude.slice -- /usr/bin/env claude
end
# Never exec here. tmux-resurrect's ps save strategy reads the *children* of
# the pane pid (`ps -ao ppid,args | grep "^$pane_pid"`), so exec'ing would make
# claude the pane pid itself and the saved command would be one of claude's own
# subprocesses — restore then silently does nothing. Keeping fish as the pane
# process is what puts "claude --session-id <uuid>" where resurrect looks.
# Claude exiting drops back to a prompt rather than closing the pane.
# Restore path: resurrect replays the id we launched with. Claude rejects
# --session-id for an id that already exists, so switch to --resume once a
# transcript for it is on disk.
if test (count $argv) -ge 2
and contains -- $argv[1] --session-id --resume
and string match -qir '^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$' -- $argv[2]
set -l id $argv[2]
set -l transcript (find $HOME/.claude/projects -maxdepth 2 -name "$id.jsonl" -print -quit)
if test -n "$transcript"
$launch --resume $id $argv[3..]
return
end
$launch --session-id $id $argv[3..]
return
end
# An explicit session flag means the caller is choosing the conversation.
for flag in -c --continue -r --resume --session-id
if contains -- $flag $argv
$launch $argv
return
end
end
$launch --session-id (uuidgen) $argv
end
+3 -19
View File
@@ -1,20 +1,4 @@
function record -d "Capture a screen recording; -a/--audio adds desktop and mic audio"
argparse a/audio -- $argv; or return
if not set -q _flag_audio
wf-recorder -c libopenh264 --no-audio -g "$(slurp)" -f output.mp4
return
end
# wf-recorder takes a single audio source, so mix the mic and desktop
# into a temporary null sink and record its monitor.
set -l modules (pactl load-module module-null-sink sink_name=record_mix sink_properties=device.description=record_mix)
set -a modules (pactl load-module module-loopback source=(pactl get-default-source) sink=record_mix)
set -a modules (pactl load-module module-loopback source=(pactl get-default-sink).monitor sink=record_mix)
wf-recorder -c libopenh264 --audio=record_mix.monitor -g "$(slurp)" -f output.mp4
for m in $modules[-1..1]
pactl unload-module $m
end
function record -d "Capture a screen recording with no audio"
wf-recorder -c libopenh264 --no-audio -g "$(slurp)" -f output.mp4
end
-3
View File
@@ -1,3 +0,0 @@
function voyager -d "SSH into voyager, attaching to its tmux session or starting one"
ssh -t voyager 'tmux attach || tmux new-session -s main'
end
@@ -0,0 +1,30 @@
# name: 'Catppuccin Latte'
# url: 'https://github.com/catppuccin/fish'
# preferred_background: eff1f5
fish_color_normal 4c4f69
fish_color_command 1e66f5
fish_color_param dd7878
fish_color_keyword 8839ef
fish_color_quote 40a02b
fish_color_redirection ea76cb
fish_color_end fe640b
fish_color_comment 8c8fa1
fish_color_error d20f39
fish_color_gray 9ca0b0
fish_color_selection --background=ccd0da
fish_color_search_match --background=ccd0da
fish_color_option 40a02b
fish_color_operator ea76cb
fish_color_escape e64553
fish_color_autosuggestion 9ca0b0
fish_color_cancel d20f39
fish_color_cwd df8e1d
fish_color_user 179299
fish_color_host 1e66f5
fish_color_host_remote 40a02b
fish_color_status d20f39
fish_pager_color_progress 9ca0b0
fish_pager_color_prefix ea76cb
fish_pager_color_completion 4c4f69
fish_pager_color_description 9ca0b0
+46
View File
@@ -0,0 +1,46 @@
font=JetBrainsMonoNerdFontMono:size=12
# Should automatically use these.
#font-bold=JetBrainsMonoNerdFontMono:weight=bold
#font-italic=JetBrainsMonoNerdFontMono:slant=italic
#font-bold-italic=JetBrainsMonoNerdFontMono:weight=bold:slant=italic
#
# Catppuccine Latte
# https://github.com/catppuccin/foot
#
[colors]
cursor=eff1f5 dc8a78
foreground=4c4f69
background=eff1f5
regular0=5c5f77
regular1=d20f39
regular2=40a02b
regular3=df8e1d
regular4=1e66f5
regular5=ea76cb
regular6=179299
regular7=acb0be
bright0=6c6f85
bright1=d20f39
bright2=40a02b
bright3=df8e1d
bright4=1e66f5
bright5=ea76cb
bright6=179299
bright7=bcc0cc
16=fe640b
17=dc8a78
selection-foreground=4c4f69
selection-background=ccced7
search-box-no-match=dce0e8 d20f39
search-box-match=4c4f69 ccd0da
jump-labels=dce0e8 fe640b
urls=1e66f5
+1 -9
View File
@@ -1,13 +1,5 @@
# NOTE: ghostty runs as a single background process.
# Restarting requires killing that process, not just closing the window.
theme = light:Catppuccin Latte,dark:Catppuccin Mocha
theme = Catppuccin Latte
font-family = JetBrainsMono Nerd Font Mono
# https://pi.dev/docs/latest/terminal-setup
keybind = alt+backspace=text:\x1b\x7f
# Claude Code newline; matches the old Alacritty binding and works through tmux
keybind = shift+enter=text:\x1b\r
shell-integration-features = ssh-terminfo,ssh-env
+1
View File
@@ -0,0 +1 @@
theme = "catppuccin-latte"
+4
View File
@@ -0,0 +1,4 @@
{
"version": 1,
"lastSeenCliVersion": "0.14.1"
}
+1 -3
View File
@@ -8,12 +8,10 @@ notARepository: 'skip'
git:
autoForwardBranches: "none"
diffRenderers:
- command: delta --light --paging=never --line-numbers --hyperlinks --hyperlinks-file-link-format="lazygit-edit://{path}:{line}"
- command: delta --paging=never --line-numbers --hyperlinks --hyperlinks-file-link-format="lazygit-edit://{path}:{line}"
- command: delta --paging=never --line-numbers --no-gitconfig --light
os:
editPreset: "nvim"
# Using OSC 52 to copy. This should work in tmux and Remote Agent Console.
copyToClipboardCmd: printf "\033]52;c;$(printf {{text}} | base64 -w 0)\a" > /dev/tty
gui:
useHunkModeInStagingView: true
timeFormat: "2006-01-02"
-28
View File
@@ -1,28 +0,0 @@
# Dark overrides, layered on config.yml by the lazygit fish function.
git:
diffRenderers:
- command: delta --dark --paging=never --line-numbers --hyperlinks --hyperlinks-file-link-format="lazygit-edit://{path}:{line}"
- command: delta --paging=never --line-numbers --no-gitconfig --dark
gui:
theme:
activeBorderColor:
- "#a6e3a1"
- bold
inactiveBorderColor:
- "#a6adc8"
optionsTextColor:
- "#89b4fa"
selectedLineBgColor:
- "#313244"
cherryPickedCommitBgColor:
- "#45475a"
cherryPickedCommitFgColor:
- "#a6e3a1"
unstagedChangesColor:
- "#f38ba8"
defaultFgColor:
- "#cdd6f4"
searchingActiveBorderColor:
- "#f9e2af"
authorColors:
"*": "#b4befe"
+4 -5
View File
@@ -17,8 +17,8 @@ minimum_release_age = "14d"
"aqua:F1bonacc1/process-compose" = "1.120.0"
"aqua:neovim/neovim" = "0.12.4"
"github:Satty-org/Satty" = "0.20.1"
"npm:@anthropic-ai/sandbox-runtime" = "0.0.79"
"npm:@earendil-works/pi-coding-agent" = "1.2.0"
"npm:@anthropic-ai/sandbox-runtime" = "0.0.67"
"npm:@earendil-works/pi-coding-agent" = "0.83.0"
"npm:typescript" = "7.0.2"
"npm:typescript-language-server" = "5.3.0"
bat = "0.26.1"
@@ -29,12 +29,11 @@ eza = "0.23.5"
fd = "10.4.2"
gh = "2.97.0"
jq = "1.8.2"
lazygit = "0.65.1"
lazygit = "0.64.1"
node = "24.18.1"
opencode = "1.15.11"
pnpm = "12.8.1"
pnpm = "11.18.0"
restic = "0.19.1"
ripgrep = "15.2.0"
tmux = "3.7b"
uv = "0.12.0"
"npm:oh-my-codex" = "v0.21.0"
+1
View File
@@ -34,6 +34,7 @@
"persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" },
"plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" },
"render-markdown.nvim": { "branch": "main", "commit": "4663eb3ecd538bd5062628fb6d95bbe6bdca78f6" },
"sidekick.nvim": { "branch": "main", "commit": "208e1c5b8170c01fd1d07df0139322a76479b235" },
"snacks.nvim": { "branch": "main", "commit": "882c996cf28183f4d63640de0b4c02ec886d01f2" },
"todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" },
"tokyonight.nvim": { "branch": "main", "commit": "cdc07ac78467a233fd62c493de29a17e0cf2b2b6" },
+3 -1
View File
@@ -1,5 +1,6 @@
{
"extras": [
"lazyvim.plugins.extras.ai.sidekick",
"lazyvim.plugins.extras.coding.mini-surround",
"lazyvim.plugins.extras.editor.mini-diff",
"lazyvim.plugins.extras.formatting.prettier",
@@ -7,6 +8,7 @@
"lazyvim.plugins.extras.lang.go",
"lazyvim.plugins.extras.lang.json",
"lazyvim.plugins.extras.lang.markdown",
"lazyvim.plugins.extras.lang.svelte",
"lazyvim.plugins.extras.lang.tailwind",
"lazyvim.plugins.extras.lang.typescript",
"lazyvim.plugins.extras.lang.yaml",
@@ -17,4 +19,4 @@
"NEWS.md": "11866"
},
"version": 8
}
}
+1 -1
View File
@@ -30,7 +30,7 @@ require("lazy").setup({
version = false, -- always use the latest git commit
-- version = "*", -- try installing the latest stable version for plugins that support semver
},
install = { colorscheme = { "catppuccin" } },
install = { colorscheme = { "catppuccin-latte" } },
checker = {
enabled = true, -- check for plugin updates periodically
notify = false, -- notify on update
+2 -24
View File
@@ -11,27 +11,5 @@ vim.g.lazyvim_prettier_needs_config = true
-- Use eslint for formatting.
vim.g.lazyvim_eslint_auto_format = true
-- Inside tmux, copy with OSC 52: tmux forwards it to the outer terminal over ssh, and RAC
-- hands it to the browser. Paste returns this nvim's last copy instead of asking the
-- terminal for the clipboard, which waits up to 10 seconds for a reply.
if vim.env.TMUX then
local osc52 = require("vim.ui.clipboard.osc52")
local last = {}
local function copy(reg)
local send = osc52.copy(reg)
return function(lines, regtype)
last[reg] = { lines, regtype }
send(lines)
end
end
local function paste(reg)
return function()
return last[reg] or { { "" }, "v" }
end
end
vim.g.clipboard = {
name = "OSC 52",
copy = { ["+"] = copy("+"), ["*"] = copy("*") },
paste = { ["+"] = paste("+"), ["*"] = paste("*") },
}
end
-- Only run prettier in directories where there is a config file.
vim.g.lazyvim_prettier_needs_config = false
@@ -1,7 +1,6 @@
return {
"LazyVim/LazyVim",
opts = {
-- Flavour follows 'background', which nvim updates from the terminal.
colorscheme = "catppuccin",
colorscheme = "catppuccin-latte",
},
}
-26
View File
@@ -1,26 +0,0 @@
set $rosewater #f5e0dc
set $flamingo #f2cdcd
set $pink #f5c2e7
set $mauve #cba6f7
set $red #f38ba8
set $maroon #eba0ac
set $peach #fab387
set $yellow #f9e2af
set $green #a6e3a1
set $teal #94e2d5
set $sky #89dceb
set $sapphire #74c7ec
set $blue #89b4fa
set $lavender #b4befe
set $text #cdd6f4
set $subtext1 #bac2de
set $subtext0 #a6adc8
set $overlay2 #9399b2
set $overlay1 #7f849c
set $overlay0 #6c7086
set $surface2 #585b70
set $surface1 #45475a
set $surface0 #313244
set $base #1e1e2e
set $mantle #181825
set $crust #11111b
+7 -8
View File
@@ -11,7 +11,7 @@ set $down j
set $up k
set $right l
# Your preferred terminal emulator
set $term ghostty
set $term alacritty
# Your preferred application launcher
# Note: pass the final command to swaymsg so that the resulting window can be opened
# on the original workspace that the command was run on.
@@ -52,10 +52,11 @@ output * bg /usr/share/backgrounds/default.jxl fill
# Lock after 6 minutes (1 minute longer than rest break).
set $lock_timeout 360
exec /home/tgrosinger/code/wlr-break-timer/break-idle 5
exec swayidle -w \
before-sleep '/home/tgrosinger/code/wlr-break-timer/break-event sleep' \
after-resume '/home/tgrosinger/code/wlr-break-timer/break-event wake'
timeout 5 '/home/tgrosinger/code/wlr-break-timer/break-event idle_start' \
resume '/home/tgrosinger/code/wlr-break-timer/break-event idle_end' \
before-sleep '/home/tgrosinger/code/wlr-break-timer/break-event idle_start' \
after-resume '/home/tgrosinger/code/wlr-break-timer/break-event idle_end'
### Input configuration
# You can get the names of your inputs by running: swaymsg -t get_inputs
@@ -92,7 +93,7 @@ input "2362:628:PIXA3854:00_093A:0274_Touchpad" {
bindsym $mod+Equal exec /home/tgrosinger/.config/rofi/scripts/qalc.sh
# Lazygit
bindsym $mod+g exec $term --title=Floating-Lazygit -e fish -c lazygit; grab_focus; floating enable
bindsym $mod+g exec $term --title Floating-Lazygit --command /home/linuxbrew/.linuxbrew/bin/lazygit; grab_focus; floating enable
for_window [title="Floating-Lazygit"] floating enable
for_window [title="Floating-Lazygit"] resize set 1800 1200
@@ -251,9 +252,7 @@ no_focus [class="Handy"]
# Theme
#
# Palette follows the system color-scheme at load; waybar/theme.sh re-applies
# the client.* colors below live on toggle.
include 'catppuccin-$(gsettings get org.gnome.desktop.interface color-scheme | grep -q dark && echo mocha || echo latte)'
include catppuccin-latte
# target title bg text indicator border
client.focused $lavender $surface0 $text $rosewater $lavender
+3 -19
View File
@@ -17,6 +17,7 @@
"modules-right": [
"custom/break-timer",
"custom/claude",
"idle_inhibitor",
"privacy",
"pulseaudio",
"network",
@@ -24,8 +25,6 @@
"cpu",
"custom/memtmp",
//"temperature",
"idle_inhibitor",
"custom/theme",
"backlight",
//"sway/language",
"battery",
@@ -95,19 +94,11 @@
"exec": "break-status",
"return-type": "json",
"interval": 2,
"format": "{} ⌛",
"tooltip": true,
"format": "{} {icon}",
"format-icons": {
"normal": "⌛",
"reading": "📖",
"snoozed": "💤"
},
"menu": "on-click",
"menu-file": "/home/tgrosinger/code/wlr-break-timer/menu.xml",
"menu-actions": {
"start-break": "break-event start-break",
"snooze": "break-event snooze",
"toggle-reading": "break-event toggle-reading",
"skip-long": "break-event skip_long",
"toggle-pause": "break-event toggle-pause"
}
@@ -116,7 +107,7 @@
"exec": "/home/tgrosinger/code/wlr-claude-usage/claude_usage_waybar.py",
"return-type": "json",
"interval": 300,
"format": "{} 🚀"
"format": "{} 🚀",
},
"idle_inhibitor": {
"format": "{icon}",
@@ -125,13 +116,6 @@
"deactivated": ""
}
},
"custom/theme": {
"exec": "bash $HOME/.config/waybar/theme.sh",
"interval": "once",
"signal": 9,
"tooltip-format": "Toggle light/dark mode",
"on-click": "bash $HOME/.config/waybar/theme.sh toggle"
},
"privacy": {
"icon-spacing": 4,
"icon-size": 18,
-26
View File
@@ -1,26 +0,0 @@
@define-color rosewater #f5e0dc;
@define-color flamingo #f2cdcd;
@define-color pink #f5c2e7;
@define-color mauve #cba6f7;
@define-color red #f38ba8;
@define-color maroon #eba0ac;
@define-color peach #fab387;
@define-color yellow #f9e2af;
@define-color green #a6e3a1;
@define-color teal #94e2d5;
@define-color sky #89dceb;
@define-color sapphire #74c7ec;
@define-color blue #89b4fa;
@define-color lavender #b4befe;
@define-color text #cdd6f4;
@define-color subtext1 #bac2de;
@define-color subtext0 #a6adc8;
@define-color overlay2 #9399b2;
@define-color overlay1 #7f849c;
@define-color overlay0 #6c7086;
@define-color surface2 #585b70;
@define-color surface1 #45475a;
@define-color surface0 #313244;
@define-color base #1e1e2e;
@define-color mantle #181825;
@define-color crust #11111b;
-12
View File
@@ -1,12 +0,0 @@
@import "mocha.css";
@import "style.css";
/* Mocha's pastel accents need dark text; @text is light here. */
#battery.warning:not(.charging),
#battery.critical:not(.charging),
#custom-break-timer.warning,
#custom-break-timer.paused,
#custom-break-timer.overdue-short,
#custom-break-timer.overdue-long {
color: @base;
}
-2
View File
@@ -1,2 +0,0 @@
@import "latte.css";
@import "style.css";
+4 -17
View File
@@ -1,5 +1,7 @@
@import "latte.css";
* {
font-family: 'Ubuntu Nerd Font';
font-family: 'JetBrainsMono Nerd Font';
font-size: 13px;
}
@@ -170,10 +172,6 @@ label:focus {
background-color: @crust;
}
#custom-theme {
padding: 0 6px 0 10px;
}
#custom-claude-usage {
padding: 0 5px;
}
@@ -198,11 +196,8 @@ label:focus {
background-color: @sky;
}
#custom-break-timer.snoozed {
background-color: @mauve;
}
#custom-break-timer.overdue {
background-color: @red;
animation-name: blink;
animation-duration: 0.5s;
animation-timing-function: steps(12);
@@ -210,14 +205,6 @@ label:focus {
animation-direction: alternate;
}
#custom-break-timer.overdue-short {
background-color: @peach;
}
#custom-break-timer.overdue-long {
background-color: @red;
}
#pulseaudio.muted {
background-color: @crust;
color: @subtext1;
-39
View File
@@ -1,39 +0,0 @@
#!/usr/bin/env bash
# Waybar custom module: light/dark toggle. Waybar itself follows the portal
# appearance by loading style-light.css / style-dark.css. Sway picks its
# palette at config load; rather than `swaymsg reload` (which restarts waybar,
# killing this script's parent), re-send its client.* lines with the new colors.
key="org.gnome.desktop.interface color-scheme"
dark() { [[ $(gsettings get $key) == *dark* ]]; }
# btop.conf points at current.theme (gitignored); SIGUSR2 makes btop reload it.
btop_theme() {
ln -sfn "catppuccin_$1.theme" "$HOME/.config/btop/themes/current.theme"
pkill -USR2 -x btop
}
if [[ $1 == toggle ]]; then
# GTK3 apps (incl. Firefox's UI and extension sidebars) ignore color-scheme
# and only follow gtk-theme.
if dark; then
gsettings set $key prefer-light; flavour=latte
gsettings set org.gnome.desktop.interface gtk-theme Adwaita
else
gsettings set $key prefer-dark; flavour=mocha
gsettings set org.gnome.desktop.interface gtk-theme Adwaita-dark
fi
pkill -RTMIN+9 -x waybar
sway=$HOME/.config/sway
swaymsg "$(grep '^client\.' "$sway/config" \
| sed -f <(sed -E 's/^set \$(\S+) (\S+)/s|\\$\1\\b|\2|g/' "$sway/catppuccin-$flavour") \
| paste -sd';')" >/dev/null
elif dark; then
# This branch runs at waybar startup and after each toggle, so it keeps
# dunst (D-Bus activated with plain dunstrc) and btop in sync.
dunstctl reload "$HOME/.config/dunst/dunstrc" "$HOME/.config/dunst/mocha.conf" >/dev/null
btop_theme mocha
echo $''
else
dunstctl reload >/dev/null
btop_theme latte
echo $''
fi
+1
View File
@@ -64,6 +64,7 @@
# Does not behave well for comments
#features = catppuccin-latte
navigate = true
light = true
side-by-side = true
line-numbers = true
#map-styles = bold purple => syntax magenta, bold cyan => syntax blue
-8
View File
@@ -1,8 +0,0 @@
#!/usr/bin/env bash
# lazygit with the palette matching the terminal's light/dark theme (CSI ? 997 ; 1 n is dark)
cfg=$HOME/.config/lazygit/config.yml
printf '\e[?996n' >/dev/tty
IFS= read -rsd n -t 0.5 reply </dev/tty
[[ $reply == *'997;1' ]] && cfg=$cfg,$HOME/.config/lazygit/mocha.yml
LG_CONFIG_FILE=$cfg exec lazygit "$@"
+5 -5
View File
@@ -1,12 +1,12 @@
{
"lastChangelogVersion": "0.83.0",
"theme": "catppuccin-latte/catppuccin-mocha",
"defaultProvider": "openai",
"defaultModel": "gpt-6.1-sol",
"theme": "catppuccin-latte",
"defaultProvider": "openai-codex",
"defaultModel": "gpt-5.6-luna",
"defaultThinkingLevel": "high",
"skills": [
"~/.agents/skills"
"~/.claude/skills"
],
"hideThinkingBlock": true,
"enableInstallTelemetry": false
}
}
+30 -36
View File
@@ -1,6 +1,6 @@
{
"$schema": "https://pi.dev/schemas/theme.schema.json",
"name": "catppuccin-latte",
"$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
"name": "catppuccin-tui-latte",
"vars": {
"rosewater": "#dc8a78",
"flamingo": "#dd7878",
@@ -31,66 +31,60 @@
},
"colors": {
"accent": "mauve",
"border": "blue",
"borderAccent": "sapphire",
"borderMuted": "surface0",
"border": "surface2",
"borderAccent": "lavender",
"borderMuted": "surface1",
"success": "green",
"error": "red",
"warning": "yellow",
"muted": "overlay1",
"dim": "overlay0",
"muted": "subtext0",
"dim": "overlay1",
"text": "text",
"thinkingText": "overlay1",
"thinkingText": "subtext1",
"selectedBg": "surface0",
"userMessageBg": "surface0",
"userMessageText": "text",
"customMessageBg": "surface1",
"customMessageBg": "mantle",
"customMessageText": "text",
"customMessageLabel": "mauve",
"toolPendingBg": "mantle",
"toolSuccessBg": "#cce1cd",
"toolErrorBg": "#e9c4cf",
"toolTitle": "text",
"toolOutput": "subtext0",
"mdHeading": "peach",
"toolSuccessBg": "surface0",
"toolErrorBg": "surface0",
"toolTitle": "blue",
"toolOutput": "overlay2",
"mdHeading": "mauve",
"mdLink": "blue",
"mdLinkUrl": "overlay0",
"mdCode": "teal",
"mdCodeBlock": "green",
"mdCodeBlockBorder": "overlay1",
"mdLinkUrl": "sapphire",
"mdCode": "peach",
"mdCodeBlock": "subtext1",
"mdCodeBlockBorder": "surface2",
"mdQuote": "subtext0",
"mdQuoteBorder": "overlay1",
"mdHr": "overlay1",
"mdQuoteBorder": "surface2",
"mdHr": "surface2",
"mdListBullet": "mauve",
"toolDiffAdded": "green",
"toolDiffRemoved": "red",
"toolDiffContext": "overlay1",
"syntaxComment": "overlay0",
"toolDiffContext": "subtext0",
"syntaxComment": "overlay2",
"syntaxKeyword": "mauve",
"syntaxFunction": "blue",
"syntaxVariable": "text",
"syntaxVariable": "maroon",
"syntaxString": "green",
"syntaxNumber": "peach",
"syntaxType": "yellow",
"syntaxOperator": "sky",
"syntaxPunctuation": "overlay2",
"thinkingOff": "surface0",
"thinkingMinimal": "overlay0",
"thinkingOff": "surface1",
"thinkingMinimal": "surface2",
"thinkingLow": "blue",
"thinkingMedium": "sapphire",
"thinkingHigh": "mauve",
"thinkingXhigh": "pink",
"bashMode": "green"
"thinkingXhigh": "red",
"bashMode": "peach"
},
"export": {
"pageBg": "base",
"cardBg": "mantle",
"infoBg": "surface0"
"pageBg": "#eff1f5",
"cardBg": "#e6e9ef",
"infoBg": "#ccd0da"
}
}
@@ -1,96 +0,0 @@
{
"$schema": "https://pi.dev/schemas/theme.schema.json",
"name": "catppuccin-mocha",
"vars": {
"rosewater": "#f5e0dc",
"flamingo": "#f2cdcd",
"pink": "#f5c2e7",
"mauve": "#cba6f7",
"red": "#f38ba8",
"maroon": "#eba0ac",
"peach": "#fab387",
"yellow": "#f9e2af",
"green": "#a6e3a1",
"teal": "#94e2d5",
"sky": "#89dceb",
"sapphire": "#74c7ec",
"blue": "#89b4fa",
"lavender": "#b4befe",
"text": "#cdd6f4",
"subtext1": "#bac2de",
"subtext0": "#a6adc8",
"overlay2": "#9399b2",
"overlay1": "#7f849c",
"overlay0": "#6c7086",
"surface2": "#585b70",
"surface1": "#45475a",
"surface0": "#313244",
"base": "#1e1e2e",
"mantle": "#181825",
"crust": "#11111b"
},
"colors": {
"accent": "mauve",
"border": "blue",
"borderAccent": "sapphire",
"borderMuted": "surface0",
"success": "green",
"error": "red",
"warning": "yellow",
"muted": "overlay1",
"dim": "overlay0",
"text": "text",
"thinkingText": "overlay1",
"selectedBg": "surface0",
"userMessageBg": "surface0",
"userMessageText": "text",
"customMessageBg": "surface1",
"customMessageText": "text",
"customMessageLabel": "mauve",
"toolPendingBg": "mantle",
"toolSuccessBg": "#3e4b4c",
"toolErrorBg": "#4c3a4c",
"toolTitle": "text",
"toolOutput": "subtext0",
"mdHeading": "peach",
"mdLink": "blue",
"mdLinkUrl": "overlay0",
"mdCode": "teal",
"mdCodeBlock": "green",
"mdCodeBlockBorder": "overlay1",
"mdQuote": "subtext0",
"mdQuoteBorder": "overlay1",
"mdHr": "overlay1",
"mdListBullet": "mauve",
"toolDiffAdded": "green",
"toolDiffRemoved": "red",
"toolDiffContext": "overlay1",
"syntaxComment": "overlay0",
"syntaxKeyword": "mauve",
"syntaxFunction": "blue",
"syntaxVariable": "text",
"syntaxString": "green",
"syntaxNumber": "peach",
"syntaxType": "yellow",
"syntaxOperator": "sky",
"syntaxPunctuation": "overlay2",
"thinkingOff": "surface0",
"thinkingMinimal": "overlay0",
"thinkingLow": "blue",
"thinkingMedium": "sapphire",
"thinkingHigh": "mauve",
"thinkingXhigh": "pink",
"bashMode": "green"
},
"export": {
"pageBg": "crust",
"cardBg": "mantle",
"infoBg": "surface0"
}
}
+13 -10
View File
@@ -5,11 +5,7 @@ set-option -g renumber-windows on
set-option -g history-limit 10000
set -s escape-time 0
set-option -g detach-on-destroy off
# This is a variant on the choose-tree hook that filters out Remote Access Console throw-away sessions
# to prevent dropping me into the session picker for automated actions.
#set-hook -g session-closed 'choose-tree -Zs'
set-hook -g session-closed 'if -F "#{||:#{m:rac-*,#{hook_session_name}},#{client_control_mode}}" "" "choose-tree -Zs"'
set-hook -g session-closed 'choose-tree -Zs'
### Fix supporting italics
set -g default-terminal "tmux-256color"
@@ -68,12 +64,8 @@ set -g status-right '#(date "+%%Y-%m-%d %%H:%%M:%%S")'
# bell
set-window-option -g window-status-bell-style fg=white,bg=red #base2, red
# Color Scheme: flavour follows the system at startup, then the terminal's
# light/dark reports (mode 2031) while attached.
# Color Scheme
set -g @catppuccin_flavour 'latte'
if 'gsettings get org.gnome.desktop.interface color-scheme | grep -q dark' "set -g @catppuccin_flavour 'mocha'"
set-hook -g client-dark-theme "set -g @catppuccin_flavour 'mocha'; run ~/.tmux/plugins/tmux/catppuccin.tmux"
set-hook -g client-light-theme "set -g @catppuccin_flavour 'latte'; run ~/.tmux/plugins/tmux/catppuccin.tmux"
set -g @catppuccin_window_left_separator ""
set -g @catppuccin_window_middle_separator ""
set -g @catppuccin_window_right_separator "█ "
@@ -92,6 +84,17 @@ set -g @catppuccin_window_status_enable "no"
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'catppuccin/tmux'
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-continuum'
# Session persistence (resurrect + continuum)
set -g @continuum-restore 'on'
set -g @continuum-save-interval '5'
set -g @resurrect-capture-pane-contents 'on'
set -g @resurrect-strategy-nvim 'session'
# Claude panes are saved as `claude --session-id <uuid>`; dev-claude turns that
# saved command line back into a resume of that exact conversation.
set -g @resurrect-processes '"claude->dev-claude *"'
# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
run '~/.tmux/plugins/tpm/tpm'