# Project Manager

> Manage Espen's projects across the Dev folder and Obsidian vault. Use for project status checks, creating new projects, syncing between code repos and vault notes, archiving, and cross-project search.

- Skill: `espennilsen/project-manager` (Agent Skill)
- Install (CLI): `npx skillmds@latest add espennilsen/project-manager`
- Raw SKILL.md: https://api.skillmd.com/api/skills/espennilsen/project-manager/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: espennilsen (https://skillmd.com/u/espennilsen)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/espennilsen/project-manager

---


# Project Manager

Manage projects spanning two systems:
- **Code** — `/Users/espen/Dev/` (git repos, code, configs)
- **Knowledge** — Obsidian vault at `/Users/espen/Library/CloudStorage/OneDrive-Espennilsen.net/2-Areas/Digital_Life/Obsidian/e9n` (notes, tasks, dashboards)

## ⚠️ Safety

- **Always confirm before modifying Obsidian vault files.** The vault has Dataview queries, templates, and dashboards that depend on consistent structure.
- **Read the vault's `AGENTS.md` and relevant `_Index.md` files** before creating or editing vault notes.
- **Never force-push, delete branches, or reset git history** without explicit confirmation.

## Paths

```bash
DEV="/Users/espen/Dev"
VAULT="/Users/espen/Library/CloudStorage/OneDrive-Espennilsen.net/2-Areas/Digital_Life/Obsidian/e9n"
```

## Known Projects

Active projects and their locations. Resolve project references against this list first.

| Project | Dev Path | Vault Path | Stack |
|---------|----------|------------|-------|
| pi (Hannah) | `$DEV/pi` | `1. Projects/AI Projects/Pi (Hannah)` | Node/TypeScript, Pi agent |
| e9n.dev | `$DEV/e9n.dev` | `1. Projects/e9n Agency` | Eleventy + Tailwind + Pagefind |
| Starheim | `$DEV/Starheim` | `1. Projects/Starheim` | TanStack Start + React + Clerk + oRPC |
| x10s | `$DEV/x10s` | — | Node/TypeScript |
| x10s-pi | `$DEV/x10s-pi` | — | Monorepo, Docker + K8s |
| Hovdan Seil AS | `$DEV/Hovdan Seil AS` | — | Eleventy + Tailwind |
| hjernedal.no | `$DEV/hjernedal.no` | — | Next.js + Prisma + AI chatbot |
| SalesGPT | `$DEV/SalesGPT` | — | Autonomous sales agent |
| obsidian-agent | `$DEV/obsidian-agent` | — | Claude SDK + Obsidian |
| MCP-Bridge | `$DEV/MCP-Bridge` | — | OpenAI API → MCP bridge |
| stoic-tracker | `$DEV/stoic-tracker` | — | Monorepo, Docker |
| Sail La Vie | `$DEV/Sail La Vie` | — | TanStack React + Firebase |
| LocalBooks | `$DEV/LocalBooks` | — | React Native |
| comfyui-cheatsheet | `$DEV/comfyui-cheatsheet` | — | Vue.js |
| ClaudeCode | `$DEV/ClaudeCode` | — | Developer toolkit |
| CrewMap | — | `1. Projects/CrewMap` | — |
| VibeBox | — | `1. Projects/VibeBox` | — |
| Languages | — | `1. Projects/Languages` | Thai + Spanish |
| Health | — | `1. Projects/Health` | Bodybuilding, C25K, Weight Loss |
| Sales Coaching | — | `1. Projects/Sales Coaching` | MEDDPICC |
| University Courses | — | `1. Projects/University Courses` | Academic |

## Operations

### 1. Project Status Overview

Get a quick status across all active projects:

```bash
# All git repos sorted by last commit (most recent first)
# Shows: project name, last commit timestamp, dirty file count
(for d in $DEV/*/; do
  [ -d "$d/.git" ] || continue
  name=$(basename "$d")
  ts=$(git -C "$d" log -1 --format='%ct' 2>/dev/null)
  date=$(git -C "$d" log -1 --format='%ai' 2>/dev/null | cut -d' ' -f1)
  ago=$(git -C "$d" log -1 --format='%ar' 2>/dev/null)
  dirty=$(git -C "$d" status --porcelain 2>/dev/null | wc -l | tr -d ' ')
  week=$(git -C "$d" log --oneline --since="7 days ago" --no-merges 2>/dev/null | wc -l | tr -d ' ')
  flag=""
  [ "$dirty" -gt 0 ] && flag=" ⚠️ ${dirty} dirty"
  [ "$week" -gt 0 ] && flag="${flag} 📝 ${week} this week"
  echo "${ts:-0}|${name}|${date:-never}|${ago:-never}${flag}"
done) | sort -t'|' -k1 -rn | cut -d'|' -f2-
```

```bash
# Obsidian project status
cat "$VAULT/1. Projects/_Index.md"
```

### 2. Single Project Deep Dive

For a specific project, gather comprehensive status:

```bash
PROJECT="project-name"

# Git status
git -C "$DEV/$PROJECT" status
git -C "$DEV/$PROJECT" log --oneline -10

# Recent changes
git -C "$DEV/$PROJECT" diff --stat HEAD~5 2>/dev/null

# Tech stack detection
ls "$DEV/$PROJECT/package.json" "$DEV/$PROJECT/Cargo.toml" "$DEV/$PROJECT/pyproject.toml" "$DEV/$PROJECT/go.mod" 2>/dev/null
cat "$DEV/$PROJECT/package.json" 2>/dev/null | head -20

# README / docs
cat "$DEV/$PROJECT/README.md" 2>/dev/null | head -50

# Open issues (if using GitHub)
# Check for TODO/FIXME/HACK
grep -rn "TODO\|FIXME\|HACK\|XXX" "$DEV/$PROJECT/src/" --include="*.ts" --include="*.tsx" --include="*.js" 2>/dev/null | head -20
```

For the vault side:
```bash
# Find related vault notes
find "$VAULT" -name "*.md" -path "*/Projects/*" | xargs grep -l "$PROJECT" 2>/dev/null
```

### 3. Create New Project

When starting a new project, set up both systems:

**Dev side:**
```bash
mkdir -p "$DEV/new-project"
cd "$DEV/new-project"
git init
# ... scaffold based on stack
```

**Vault side** (confirm with Espen first):
1. Read the Project Template: `cat "$VAULT/Templates/Project Template.md"`
2. Create the project note in `1. Projects/` following the template
3. Add correct frontmatter and tags per `🏷️ Tag Taxonomy.md`
4. Update `1. Projects/_Index.md` if it's not auto-generated by Dataview

### 4. Archive a Project

Move a project to archived/inactive state:

**Dev side:**
```bash
# Ensure clean state
git -C "$DEV/$PROJECT" status
# Confirm no uncommitted work, then optionally:
mv "$DEV/$PROJECT" "$DEV/! Archive/"
```

**Vault side** (confirm first):
1. Move the project folder from `1. Projects/` to `4. Archive/`
2. Update tags: change `#project/active` to `#project/completed` or `#project/archived`
3. Add completion date to frontmatter

### 5. Cross-Project Search

Search across all code repos and vault notes:

```bash
# Search code
grep -rl "search term" $DEV/*/src/ --include="*.ts" --include="*.tsx" --include="*.py" 2>/dev/null | head -20

# Search vault
grep -rl "search term" "$VAULT" --include="*.md" 2>/dev/null | head -20

# Search git history across projects
for d in $DEV/*/; do
  [ -d "$d/.git" ] || continue
  result=$(git -C "$d" log --all --oneline --grep="search term" 2>/dev/null | head -3)
  [ -n "$result" ] && echo "=== $(basename "$d") ===" && echo "$result"
done
```

### 6. Sync Check

Verify Dev projects and Obsidian are in sync:

```bash
# Projects in Dev that might need vault notes
for d in $DEV/*/; do
  [ -d "$d/.git" ] || continue
  name=$(basename "$d")
  recent=$(git -C "$d" log -1 --format='%ar' 2>/dev/null)
  vault_match=$(find "$VAULT/1. Projects" "$VAULT/2. Areas" -name "*.md" 2>/dev/null | xargs grep -l "$name" 2>/dev/null | head -1)
  if [ -z "$vault_match" ]; then
    echo "⚠️  $name (last: $recent) — no vault note found"
  fi
done
```

```bash
# Vault projects that might not have Dev repos
for d in "$VAULT/1. Projects/"*/; do
  name=$(basename "$d")
  dev_match=$(ls -d "$DEV/$name" 2>/dev/null || ls -d "$DEV/"*"$name"* 2>/dev/null | head -1)
  if [ -z "$dev_match" ]; then
    echo "📝 $name — vault-only (no Dev repo)"
  fi
done
```

### 7. Task Management

Work with the Obsidian TaskNotes system:

```bash
# Open tasks across all projects
find "$VAULT/Tasks/" -name "*.md" -exec grep -l "#status/active\|#status/in-progress" {} \; 2>/dev/null

# Tasks for a specific project
grep -rl "$PROJECT" "$VAULT/Tasks/" --include="*.md" 2>/dev/null
```

### 8. Hannah Job Stats by Project

Query Hannah's DB for per-channel/project usage:

```bash
sqlite3 /Users/espen/Dev/pi/hannah.db "
  SELECT channel, COUNT(*) as jobs,
    printf('\$%.4f', SUM(cost_total)) as cost,
    SUM(total_tokens) as tokens,
    printf('%.1fs', AVG(duration_ms)/1000.0) as avg_dur
  FROM jobs
  WHERE created_at >= datetime('now', '-7 days')
  GROUP BY channel
  ORDER BY jobs DESC;
"
```

## Output Format

When reporting project status, use this structure:

```markdown
## Project Status: [name]

**Code:** [Dev path] | **Vault:** [vault path or "—"]
**Stack:** [tech stack]
**Last commit:** [relative time] | **Dirty:** [yes/no]

### Recent Activity
- [commit summaries or "No recent commits"]

### Open Items
- [TODOs, tasks, blockers]

### Vault Notes
- [Related notes or "No vault notes found"]
```

## Conventions

- When Espen says a project name, resolve it against the Known Projects table first
- For ambiguous names, ask which project is meant
- Default time window for "recent" is 7 days
- Always show both Dev and Vault status when both exist
- Use relative paths in output (`~/Dev/project` not full paths) for readability
- When creating vault notes, always use existing Templater templates

