sync: auto-sync from GURU-5070 at 2026-06-06 15:46:17
Author: Mike Swanson Machine: GURU-5070 Timestamp: 2026-06-06 15:46:17
This commit is contained in:
@@ -30,6 +30,11 @@ param(
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$u = $env:USERPROFILE
|
||||
|
||||
# Decode native (git) stdout as UTF-8 so captured patch text is not mangled, and give
|
||||
# us a UTF-8 (no BOM) encoding for writing patches `git apply` can actually parse.
|
||||
try { [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false) } catch {}
|
||||
$Utf8NoBom = New-Object System.Text.UTF8Encoding($false)
|
||||
|
||||
function Save($src,$dst){
|
||||
if (Test-Path -LiteralPath $src) {
|
||||
$p = Split-Path $dst -Parent; if (-not (Test-Path $p)) { New-Item -ItemType Directory -Force -Path $p | Out-Null }
|
||||
@@ -81,6 +86,37 @@ if (Test-Path "$ClaudeToolsRoot\.claude\state") { Copy-Item "$ClaudeToolsRoot\.c
|
||||
Copy-Item "$ClaudeToolsRoot\.claude\bootstrap\*.ps1" "$root\bootstrap\" -Force -ErrorAction SilentlyContinue
|
||||
Copy-Item "$ClaudeToolsRoot\.claude\bootstrap\RESTORE.md" "$root\bootstrap\" -Force -ErrorAction SilentlyContinue
|
||||
|
||||
# --- at-risk local WIP: stashes + untracked diffs that are on NO remote ---
|
||||
# Written as UTF-8 (no BOM, LF) so restore-at-risk-work.ps1 / `git apply` can parse them.
|
||||
# (Earlier ad-hoc captures used PowerShell `>` redirection = UTF-16, which git apply
|
||||
# rejects with "No valid patches in input" - hence the explicit byte-level write here.)
|
||||
$awRoot = "$root\at-risk-work"
|
||||
function Save-RepoStashes($repo,$label){
|
||||
if (-not (Test-Path "$repo\.git")) { return }
|
||||
$marks = @(& git -C $repo stash list --format='%gd' 2>$null)
|
||||
if (-not $marks) { return }
|
||||
$dir = "$awRoot\$label"; New-Item -ItemType Directory -Force -Path $dir | Out-Null
|
||||
$base = (& git -C $repo rev-parse HEAD 2>$null)
|
||||
[System.IO.File]::WriteAllText("$dir\BASE-COMMIT.txt", "$base`n", $Utf8NoBom)
|
||||
for ($i=0; $i -lt $marks.Count; $i++) {
|
||||
$files = @(& git -C $repo stash show --name-only "stash@{$i}" 2>$null)
|
||||
$slug = if ($files.Count) { ([IO.Path]::GetFileNameWithoutExtension($files[0])) -replace '[^\w\-]','_' } else { "stash$i" }
|
||||
$lines = @(& git -C $repo --no-pager stash show -p "stash@{$i}" 2>$null)
|
||||
[System.IO.File]::WriteAllText("$dir\stash$i-$slug.patch", (($lines -join "`n") + "`n"), $Utf8NoBom)
|
||||
Write-Host "[OK] at-risk stash: $label stash@{$i} -> stash$i-$slug.patch"
|
||||
}
|
||||
}
|
||||
Save-RepoStashes "$ClaudeToolsRoot\projects\msp-tools\guru-rmm" 'guru-rmm'
|
||||
Save-RepoStashes "$ClaudeToolsRoot\projects\msp-tools\guru-connect" 'guru-connect'
|
||||
# untracked working diffs (e.g. tmp-*.diff) that aren't committed anywhere
|
||||
$gcRepo = "$ClaudeToolsRoot\projects\msp-tools\guru-connect"
|
||||
if (Test-Path $gcRepo) {
|
||||
Get-ChildItem $gcRepo -Filter 'tmp-*.diff' -File -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
$dir = "$awRoot\guru-connect"; New-Item -ItemType Directory -Force -Path $dir | Out-Null
|
||||
Copy-Item $_.FullName "$dir\$($_.Name)" -Force; Write-Host "[OK] at-risk untracked diff: guru-connect\$($_.Name)"
|
||||
}
|
||||
}
|
||||
|
||||
# --- manifests ---
|
||||
$m = "$root\manifests"
|
||||
$tools = 'node','npm','claude','gemini','grok','ollama','py','git','gh','jq','sops','age','cargo','rustc','code','op'
|
||||
|
||||
@@ -15,6 +15,18 @@
|
||||
Non-destructive and re-runnable. If a patch won't apply cleanly (submodule moved on),
|
||||
it is reported and the .patch file is left in place for manual `git apply --3way`.
|
||||
|
||||
ROBUSTNESS NOTES (why this is not just `git apply <file>`):
|
||||
* Patch files may have been written by PowerShell redirection (UTF-16 LE/BE w/ BOM).
|
||||
`git apply` only understands UTF-8/ASCII and otherwise reports
|
||||
"No valid patches in input". Get-Utf8PatchPath normalizes any encoding to a
|
||||
UTF-8 (no BOM) temp copy before applying.
|
||||
* git writes progress/errors to stderr; capturing that with `2>&1` while
|
||||
$ErrorActionPreference='Stop' turns it into a *terminating* error (PS 5.1
|
||||
NativeCommandError) that aborts the whole bootstrap. Invoke-Git captures
|
||||
output without that trap and returns the real exit code.
|
||||
* If the submodule still has stashes, the WIP almost certainly survived the reset.
|
||||
Re-applying would create DUPLICATE stashes, so we skip and report instead.
|
||||
|
||||
.PARAMETER BundlePath Recovery bundle root (auto-detect F:\ then E:\).
|
||||
.PARAMETER ClaudeToolsRoot Default D:\claudetools.
|
||||
#>
|
||||
@@ -22,6 +34,35 @@
|
||||
param([string]$BundlePath,[string]$ClaudeToolsRoot='D:\claudetools')
|
||||
$ErrorActionPreference='Stop'
|
||||
|
||||
# Read a patch regardless of encoding (UTF-16 LE/BE +/- BOM, UTF-8 +/- BOM) and return
|
||||
# the path to a normalized UTF-8 (no BOM) temp copy that `git apply` can parse.
|
||||
function Get-Utf8PatchPath($path){
|
||||
$bytes = [System.IO.File]::ReadAllBytes($path)
|
||||
if ($bytes.Length -ge 2 -and $bytes[0] -eq 0xFF -and $bytes[1] -eq 0xFE) { $text = [System.Text.Encoding]::Unicode.GetString($bytes,2,$bytes.Length-2) }
|
||||
elseif ($bytes.Length -ge 2 -and $bytes[0] -eq 0xFE -and $bytes[1] -eq 0xFF) { $text = [System.Text.Encoding]::BigEndianUnicode.GetString($bytes,2,$bytes.Length-2) }
|
||||
elseif ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) { $text = [System.Text.Encoding]::UTF8.GetString($bytes,3,$bytes.Length-3) }
|
||||
else {
|
||||
# No BOM: detect UTF-16 LE without BOM by counting interleaved NUL bytes in the head.
|
||||
$nul = 0; $n = [Math]::Min(64,$bytes.Length)
|
||||
for ($i=0; $i -lt $n; $i++) { if ($bytes[$i] -eq 0) { $nul++ } }
|
||||
if ($nul -gt 8) { $text = [System.Text.Encoding]::Unicode.GetString($bytes) }
|
||||
else { $text = [System.Text.Encoding]::UTF8.GetString($bytes) }
|
||||
}
|
||||
$text = $text -replace "`r`n","`n" # normalize to LF so git apply is happy
|
||||
$tmp = [System.IO.Path]::GetTempFileName()
|
||||
[System.IO.File]::WriteAllText($tmp, $text, (New-Object System.Text.UTF8Encoding($false)))
|
||||
return $tmp
|
||||
}
|
||||
|
||||
# Run git without letting native stderr (under $ErrorActionPreference='Stop') become a
|
||||
# terminating error. Returns [pscustomobject]@{ Code; Output }.
|
||||
function Invoke-Git([string[]]$GitArgs){
|
||||
$old = $ErrorActionPreference; $ErrorActionPreference = 'Continue'
|
||||
try { $out = (& git @GitArgs 2>&1 | Out-String); $code = $LASTEXITCODE }
|
||||
finally { $ErrorActionPreference = $old }
|
||||
[pscustomobject]@{ Code = $code; Output = ($out).Trim() }
|
||||
}
|
||||
|
||||
if (-not $BundlePath) { foreach ($d in 'F:','E:','D:') { if (Test-Path "$d\claudetools-recovery\at-risk-work") { $BundlePath="$d\claudetools-recovery"; break } } }
|
||||
$aw = "$BundlePath\at-risk-work"
|
||||
if (-not $BundlePath -or -not (Test-Path $aw)) { Write-Host "[INFO] no at-risk-work folder found in bundle - nothing to restore"; return }
|
||||
@@ -32,20 +73,29 @@ function Have-Git($repo){ Test-Path "$repo\.git" }
|
||||
# ---- guru-rmm stashes ----
|
||||
$rmm = "$ClaudeToolsRoot\projects\msp-tools\guru-rmm"
|
||||
if ((Test-Path "$aw\guru-rmm") -and (Have-Git $rmm)) {
|
||||
if (git -C $rmm status --porcelain) {
|
||||
$existing = (Invoke-Git @('-C',$rmm,'stash','list')).Output
|
||||
if ($existing) {
|
||||
Write-Host "[SKIP] guru-rmm already has stashes (local WIP survived the reset) - not re-applying to avoid duplicates:" -ForegroundColor Yellow
|
||||
Write-Host $existing
|
||||
Write-Host " Bundle patches remain in $aw\guru-rmm; apply by hand if you really need them." -ForegroundColor Yellow
|
||||
}
|
||||
elseif ((Invoke-Git @('-C',$rmm,'status','--porcelain')).Output) {
|
||||
Write-Host "[WARN] guru-rmm working tree is dirty; skipping auto-restore to avoid mixing changes. Apply patches in $aw\guru-rmm manually." -ForegroundColor Yellow
|
||||
} else {
|
||||
# highest N first so stash0 lands at stash@{0}
|
||||
$patches = Get-ChildItem "$aw\guru-rmm" -Filter '*.patch' | Sort-Object Name -Descending
|
||||
foreach ($p in $patches) {
|
||||
$check = git -C $rmm apply --check --3way $p.FullName 2>&1
|
||||
if ($LASTEXITCODE -ne 0) { Write-Host "[WARN] won't apply cleanly, left for manual restore: $($p.Name) ($check)" -ForegroundColor Yellow; continue }
|
||||
git -C $rmm apply --3way $p.FullName 2>$null
|
||||
git -C $rmm stash push -u -m "restored WIP: $($p.BaseName)" 2>$null | Out-Null
|
||||
Write-Host "[OK] re-stashed guru-rmm: $($p.BaseName)" -ForegroundColor Green
|
||||
$u8 = Get-Utf8PatchPath $p.FullName
|
||||
try {
|
||||
$chk = Invoke-Git @('-C',$rmm,'apply','--check','--3way',$u8)
|
||||
if ($chk.Code -ne 0) { Write-Host "[WARN] won't apply cleanly, left for manual restore: $($p.Name) ($($chk.Output))" -ForegroundColor Yellow; continue }
|
||||
Invoke-Git @('-C',$rmm,'apply','--3way',$u8) | Out-Null
|
||||
Invoke-Git @('-C',$rmm,'stash','push','-u','-m',"restored WIP: $($p.BaseName)") | Out-Null
|
||||
Write-Host "[OK] re-stashed guru-rmm: $($p.BaseName)" -ForegroundColor Green
|
||||
} finally { Remove-Item $u8 -Force -ErrorAction SilentlyContinue }
|
||||
}
|
||||
Write-Host "[INFO] guru-rmm stashes now:" -ForegroundColor Cyan
|
||||
git -C $rmm stash list
|
||||
Write-Host (Invoke-Git @('-C',$rmm,'stash','list')).Output
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +103,11 @@ if ((Test-Path "$aw\guru-rmm") -and (Have-Git $rmm)) {
|
||||
$gc = "$ClaudeToolsRoot\projects\msp-tools\guru-connect"
|
||||
$diff = "$aw\guru-connect\tmp-spec018.diff"
|
||||
if ((Test-Path $diff) -and (Test-Path $gc)) {
|
||||
Copy-Item $diff "$gc\tmp-spec018.diff" -Force
|
||||
Write-Host "[OK] guru-connect\tmp-spec018.diff restored (untracked working file - 'git apply --3way tmp-spec018.diff' to apply it)" -ForegroundColor Green
|
||||
if (Test-Path "$gc\tmp-spec018.diff") {
|
||||
Write-Host "[SKIP] guru-connect\tmp-spec018.diff already present in repo (survived the reset) - not overwriting." -ForegroundColor Yellow
|
||||
} else {
|
||||
Copy-Item $diff "$gc\tmp-spec018.diff" -Force
|
||||
Write-Host "[OK] guru-connect\tmp-spec018.diff restored (untracked working file - 'git apply --3way tmp-spec018.diff' to apply it)" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
Write-Host "[DONE] at-risk WIP restore" -ForegroundColor Cyan
|
||||
|
||||
111
session-logs/2026-06-06-mike-mcp-gitauth-reinstall-tailscale.md
Normal file
111
session-logs/2026-06-06-mike-mcp-gitauth-reinstall-tailscale.md
Normal file
@@ -0,0 +1,111 @@
|
||||
## User
|
||||
- **User:** Mike Swanson (mike)
|
||||
- **Machine:** GURU-5070
|
||||
- **Role:** admin
|
||||
|
||||
## Session Summary
|
||||
|
||||
Started from a `/doctor` report flagging the `ticktick` MCP server as failed ("Connection closed"). Diagnosed it as a missing-dependency crash, not an OAuth issue: the local stdio server `mcp-servers/ticktick/ticktick_mcp.py` is launched with bare `python` (Python 3.12) and that interpreter was missing `httpx` and (behind a try/except) `mcp`. Installed both into 3.12, created `mcp-servers/ticktick/requirements.txt`, and verified the server starts clean. The server now shows "Pending approval" (normal trust prompt) instead of crashing.
|
||||
|
||||
Mike then stated a hard requirement: git must never sit at an interactive credential prompt — his objection to Git for Windows is the Git Credential Manager popups that hang automation, not the tooling itself. Discovered a live symptom: a backgrounded Gitea Agent push was hung on a GCM prompt (commit unpushed). Stopped it, pushed via the vault Gitea API token, then built a durable, fleet-wide non-interactive auth solution: `setup-git-auth.sh` (primes the `store` credential helper from the vault token, scoped per-repo by origin host, only seizing the helper from GCM `manager`), a backgrounded `SessionStart` hook, and `GIT_TERMINAL_PROMPT=0` / `GCM_INTERACTIVE=Never` in `settings.json` env. Corrected an earlier wrong memory (had attributed the dislike to the bash/path-mangling layer). All subsequent pushes this session used native `git.exe` via PowerShell with zero prompts.
|
||||
|
||||
Mike disclosed the machine was recently reinstalled and asked to install anything missing. Found the reinstall installed Python deps into only one of the machine's two interpreters (`py`/3.14 for vault+scripts vs `python`/3.12 for MCP servers), which is exactly why ticktick (3.12) and `vault get-field` (3.14, missing PyYAML) were both broken. Installed PyYAML into `py`, `websocket-client` into `py` (cdp.py), and persisted `grok` to the User PATH. Ollama `list` came back empty, but the 5 expected models (47.8 GB) were intact on `D:\OllamaModels` — the tray app just needed a few seconds to hydrate; restarting it loaded all 5. No 48 GB re-download. Then amended the recovery script `windows-bootstrap.ps1` (Phase 7 both interpreters + pyyaml/websocket-client; Phase 3 persist grok PATH; Phase 6 prime git auth; Phase 8 full model set + hydration guard) and documented the gotchas in `machines/guru-5070.md`.
|
||||
|
||||
Finally, Mike asked for help managing Tailscale for a tech-inept two-machine client. Recommended one tailnet per client (never merge into ACG's own), MSP holds Admin, devices enrolled as tagged nodes via pre-auth keys pushed from GuruRMM. Authored `wiki/patterns/tailscale-client-management.md` + `tailscale-client-enroll.ps1` (idempotent unattended Windows MSI install + tagged auth-key join). Scanned GuruRMM for the client (Robert Wolkin): found client `Wolkin, Robert`/site `Main` with 3 online Win11 Home agents. Mike clarified scope: connect RSW-Laptop -> front for file + printer sharing; DESKTOP-V1JT1SE is Bob's personal machine (out of scope). Created the `robert-wolkin` client stub, then added a reusable "files + printer over Tailscale (Windows)" section (SMB over the tailnet, the 445-firewall-on-Tailscale-interface gotcha, local-account auth on Home, MagicDNS FQDN, Point-and-Print via RMM, Taildrive alternative).
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- **ticktick fix is dependency install, not OAuth.** "Connection closed" on a local stdio MCP server = process crash before handshake. `/mcp` authenticate would not have helped.
|
||||
- **Non-interactive git auth via repo-local `store` helper, not global change.** Kept global GCM untouched for other repos; scoped the credential to each repo's actual origin host. `GIT_TERMINAL_PROMPT=0` enforced via committed settings.json so even an unprimed machine fails fast instead of hanging.
|
||||
- **Conservative helper override.** `setup-git-auth.sh` only switches the helper to `store` when it is empty or GCM `manager`, so a Mac osxkeychain setup is left alone — safe to run fleet-wide via SessionStart hook.
|
||||
- **Two-interpreter Python installs in bootstrap.** Root cause of the reinstall breakage; de-dupe by `sys.executable` so a single install isn't run twice.
|
||||
- **Did not re-download Ollama models.** Confirmed manifests + 47.8 GB on `D:\OllamaModels`; an empty `ollama list` right after login is a hydration-timing artifact, not "models gone."
|
||||
- **One tailnet per client.** Isolation, billing, offboarding, IdP blast radius. Never merge a client into ACG's tailnet or share one tailnet across clients.
|
||||
- **SMB over Tailscale for Wolkin (not Taildrive).** A shared printer forces SMB regardless, so use SMB for both files and printer; no subnet router because files/printer live on a node.
|
||||
- **Session log to root** (`session-logs/`) — multi-topic (machine maintenance + git infra + a client), no single article implied; wiki articles were hand-authored inline during the session.
|
||||
|
||||
## Problems Encountered
|
||||
|
||||
- **ticktick MCP "Connection closed":** missing `httpx` then `mcp` in Python 3.12. Installed both; server starts clean.
|
||||
- **Gitea Agent background push hung:** GCM credential prompt invisible in background. Stopped the agent (TaskStop), pushed with the vault API token, then made auth non-interactive permanently.
|
||||
- **`git credential approve` rejected input:** PowerShell piping mangled the multiline credential ("missing protocol field"). Wrote directly to `~/.git-credentials` idempotently instead.
|
||||
- **PowerShell commit failed on embedded double quotes:** `"see each other"` in a commit message split into stray pathspecs (PS 5.1 native-arg quoting bug). Used `git commit -F <msgfile>` / avoided embedded quotes.
|
||||
- **`vault get-field` returned empty:** `yaml-query.py` (run via `py`/3.14) missing PyYAML. Installed pyyaml; added a `get`+grep fallback to setup-git-auth.sh.
|
||||
- **Ollama `list` empty despite 47.8 GB on disk:** tray app server hydration delay (also the app vs CLI env). Restarted; all 5 models loaded. Documented as a bootstrap Phase 8 guard.
|
||||
- **GuruRMM showed 3 agents, Mike expected 2:** clarified DESKTOP-V1JT1SE is Bob's personal machine, out of Tailscale scope.
|
||||
|
||||
## Configuration Changes
|
||||
|
||||
Created:
|
||||
- `mcp-servers/ticktick/requirements.txt` — `httpx>=0.28`, `mcp>=1.27`
|
||||
- `.claude/scripts/setup-git-auth.sh` — non-interactive git auth primer
|
||||
- `.claude/memory/feedback_git_noninteractive_auth.md` — feedback memory (replaced the deleted `feedback_avoid_git_for_windows.md`)
|
||||
- `wiki/patterns/tailscale-client-management.md` — MSP Tailscale pattern
|
||||
- `wiki/patterns/tailscale-client-enroll.ps1` — GuruRMM enrollment script
|
||||
- `wiki/clients/robert-wolkin.md` — client stub
|
||||
|
||||
Modified:
|
||||
- `.claude/agents/gitea.md` — "Non-interactive auth" guidance block
|
||||
- `.claude/settings.json` — `env` (GIT_TERMINAL_PROMPT=0, GCM_INTERACTIVE=Never) + SessionStart hook for setup-git-auth.sh
|
||||
- `.claude/bootstrap/windows-bootstrap.ps1` — Phases 3, 6, 7, 8 amended
|
||||
- `.claude/machines/guru-5070.md` — Known issues (interpreter split, ollama hydration, grok PATH, git auth)
|
||||
- `.claude/memory/MEMORY.md` — index pointer
|
||||
- `wiki/index.md` — Patterns + Clients rows
|
||||
|
||||
Deleted:
|
||||
- `.claude/memory/feedback_avoid_git_for_windows.md` (superseded, never committed)
|
||||
|
||||
Machine state (not in repo):
|
||||
- Python 3.12 (`python`): installed `httpx`, `mcp`
|
||||
- Python 3.14 (`py`): installed `pyyaml`, `websocket-client`
|
||||
- User PATH: appended `~\.grok\bin` (also `~\.local\bin`, `%APPDATA%\npm`)
|
||||
- `~/.git-credentials`: two store entries (internal + public Gitea hosts); stale `%3a3000` entry removed
|
||||
- Ollama: restarted; 5 models loaded from `D:\OllamaModels`
|
||||
|
||||
## Credentials & Secrets
|
||||
|
||||
- **Gitea shared push account:** `azcomputerguru`, API token used for non-interactive push. Vault: `services/gitea.sops.yaml` field `credentials.api.api-token` (also `credentials.password`). Token cached locally in `C:\Users\guru\.git-credentials` (plaintext, local-only, scoped to `172.16.3.20:3000` + `git.azcomputerguru.com`).
|
||||
- **GuruRMM API admin:** vault `infrastructure/gururmm-server.sops.yaml` fields `credentials.gururmm-api.admin-email` / `admin-password`.
|
||||
- No new secrets created. Tailscale auth key for Wolkin not yet generated (pending Mike standing up the tailnet).
|
||||
|
||||
## Infrastructure & Servers
|
||||
|
||||
- **Gitea (internal):** `http://172.16.3.20:3000` (origin for claudetools push this session). Public: `https://git.azcomputerguru.com` (vault repo origin).
|
||||
- **GuruRMM API:** `http://172.16.3.30:3001` (JWT auth).
|
||||
- **MariaDB:** `172.16.3.30:3306` (firewall opened to 172.16.0.0/22 per incoming coord message; not exercised this session).
|
||||
- **GURU-5070 interpreters:** `py` -> Python 3.14 (`C:\Users\guru\AppData\Local\Programs\Python\...`); `python` -> Python 3.12.
|
||||
- **Ollama:** `OLLAMA_MODELS=D:\OllamaModels`, `OLLAMA_HOST=0.0.0.0:11434`. Models: nomic-embed-text, qwen3:8b, qwen3:14b, codestral:22b, qwen3.6:latest.
|
||||
|
||||
### Robert Wolkin (GuruRMM)
|
||||
- Client: `Wolkin, Robert` | Site: `Main` | site_id `2bb05f85-9fc8-4a7e-a5e5-ffe0c46431ac`
|
||||
- Agents (Win 11 Home 25H2 build 26200, agent v0.6.57, all online 2026-06-06):
|
||||
- DESKTOP-V1JT1SE — `30f6af79-ab19-4ed3-9ebc-71b2bffc2d27` — Bob's personal machine (OUT of Tailscale scope)
|
||||
- RSW-Laptop — `043fd673-35a2-4d3d-8f91-ed73ce70cc1e` — Tailscale node (connects to front)
|
||||
- front — `877d311a-4b24-462c-97b1-d2a0f7730a71` — Tailscale node (file + printer host)
|
||||
|
||||
## Commands & Outputs
|
||||
|
||||
- ticktick crash: `python ticktick_mcp.py` -> `ModuleNotFoundError: No module named 'httpx'`, then `[ERROR] MCP package not installed`.
|
||||
- Installs: `python -m pip install httpx`; `python -m pip install mcp`; `py -m pip install pyyaml`; `py -m pip install websocket-client`.
|
||||
- Non-interactive push pattern: `$env:GIT_TERMINAL_PROMPT='0'; git -C D:\ClaudeTools push origin main` (succeeds silently; PS 5.1 wraps git stderr as NativeCommandError on success — trust `$LASTEXITCODE`).
|
||||
- Prime creds: append `http://azcomputerguru:<token>@172.16.3.20:3000` to `~/.git-credentials` + repo-local `credential.helper=store`.
|
||||
- Ollama fix: stop `ollama`/`ollama app`, start `ollama app.exe`, wait ~10s -> `ollama list` shows 5 models.
|
||||
- GuruRMM lookup: `POST /api/auth/login` then `GET /api/agents`, filter `.client_name=="Wolkin, Robert"`.
|
||||
- Firewall rule (planned for `front`): `New-NetFirewallRule -DisplayName "Tailscale SMB (files+print)" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 445 -RemoteAddress 100.64.0.0/10`.
|
||||
|
||||
## Pending / Incomplete Tasks
|
||||
|
||||
- **ticktick MCP:** restart session or `/mcp` reconnect to approve (currently "Pending approval"). Crash resolved.
|
||||
- **grok:** on persistent User PATH but not callable in THIS already-running session; fine in new shells.
|
||||
- **Tailscale (Wolkin):** Mike to stand up the tailnet on Robert's account, assign himself Admin, enable MagicDNS, set `tag:wolkin` ACL, generate reusable+pre-approved tagged auth key. Then: vault the key at `clients/robert-wolkin/tailscale-authkey.sops.yaml`, enroll RSW-Laptop + front via the enroll script, push post-connect SMB config.
|
||||
- **OPEN ITEM (blocks printer step):** confirm whether the printer is USB-attached to `front` (Windows print share over SMB) or a separate network printer (install by IP on laptop, or subnet router on front).
|
||||
- **Offered, not yet done:** stage the 4 RMM jobs (firewall + share/account on front; drive map + printer on laptop); wire enroll script into a GuruRMM script library vs ad-hoc.
|
||||
- **Pre-existing WIP** (not from this session): `.claude/bootstrap/backup-to-bundle.ps1`, `restore-at-risk-work.ps1` (modified), `projects/msp-tools/guru-connect` (untracked) — swept by sync.sh `add -A`.
|
||||
|
||||
## Reference Information
|
||||
|
||||
- Commits (origin/main, pushed): `f3a175e` ticktick requirements; `9ff5a9f0` gitea agent auth docs; `162145b5` git-auth automation; `fd30af6a` bootstrap amendments + machine doc; `8d7e3805` tailscale pattern + script; `5c7e196b` wolkin stub; `32e71a13` wolkin RMM detail + scope; `f7540550` SMB files+printer pattern.
|
||||
- Vault paths: `services/gitea.sops.yaml` (`credentials.api.api-token`), `infrastructure/gururmm-server.sops.yaml` (`credentials.gururmm-api.*`).
|
||||
- Tailscale docs: subnet routers `tailscale.com/docs/features/subnet-routers`; kernel-vs-netstack `/docs/reference/kernel-vs-userspace-routers`; Windows MSI `/docs/install/windows/msi`; run unattended `/docs/how-to/run-unattended`; auth keys `/kb/1085/auth-keys`; firewall ports `/kb/1082/firewall-ports`; Taildrive `/docs/features/taildrive`.
|
||||
- Tailscale MSI silent props: `TS_UNATTENDEDMODE=always`, `TS_NOLAUNCH`, `TS_LOGINURL`, `INSTALLDIR` (no auth-key property — use `tailscale up --authkey`).
|
||||
- Wiki: `wiki/patterns/tailscale-client-management.md`, `wiki/patterns/tailscale-client-enroll.ps1`, `wiki/clients/robert-wolkin.md`.
|
||||
Reference in New Issue
Block a user