feat(skills): consolidate skill organization across agents
- Add piSkills option to ai-skills module for pi-only skills - Add ralph-work-loop skill (depends on pi extension) - Update skills.nix registry with nix-review, ralph-work-loop, ui-query - Add intent/approach/work docs for skill organization effort Universal skills deploy to claude/codex/opencode/gemini. Pi-only skills (ralph-work-loop) deploy to ~/.pi/agent/skills/ only.
This commit is contained in:
parent
796200a277
commit
9ce4c83a17
150
docs/approach/2026-01-25-skill-organization.md
Normal file
150
docs/approach/2026-01-25-skill-organization.md
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
# Approach: Skill Organization Across Agents
|
||||||
|
|
||||||
|
## Strategy
|
||||||
|
|
||||||
|
**Core philosophy**: Single source, Nix-deployed, per-repo filtered.
|
||||||
|
|
||||||
|
Skills live in dotfiles. Nix deploys them to each agent's expected location. Pi's settings handle per-repo filtering via `includeSkills`/`ignoredSkills`.
|
||||||
|
|
||||||
|
**Key Decisions**:
|
||||||
|
|
||||||
|
1. **Source location**: `~/proj/skills/skills/` vs `~/proj/dotfiles/skills/`
|
||||||
|
→ **dotfiles** — skills are config, not code. Dotfiles is the deployment source.
|
||||||
|
|
||||||
|
2. **Deployment target**: Single location vs all agent locations
|
||||||
|
→ **All locations** — deploy to `~/.claude/skills/`, `~/.codex/skills/`, `~/.config/opencode/skills/` for compatibility. Pi reads from `~/.claude/skills/` (disable other pi sources).
|
||||||
|
|
||||||
|
3. **Per-repo filtering mechanism**: Project config vs global config per repo
|
||||||
|
→ **Pi settings** — use `includeSkills`/`ignoredSkills` in project `.pi/settings.json`. Other agents don't support this, but pi is primary.
|
||||||
|
|
||||||
|
4. **Development workflow**: Direct edit in dotfiles vs edit in skills repo + deploy script
|
||||||
|
→ **Skills repo + deploy** — develop/test in `~/proj/skills/`, run `deploy-skill.sh`, Nix rebuild picks it up.
|
||||||
|
|
||||||
|
5. **Existing scattered skills**: Migrate vs leave in place
|
||||||
|
→ **Migrate** — consolidate everything to dotfiles, remove old locations after Nix manages them.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
~/proj/skills/skills/<name>/ # Development (universal)
|
||||||
|
│
|
||||||
|
│ deploy-skill.sh <name>
|
||||||
|
▼
|
||||||
|
~/proj/dotfiles/skills/<name>/ # Nix source (universal)
|
||||||
|
│
|
||||||
|
│ home-manager rebuild
|
||||||
|
▼
|
||||||
|
~/.claude/skills/<name>/ # Claude Code + Pi
|
||||||
|
~/.codex/skills/<name>/ # Codex
|
||||||
|
~/.config/opencode/skills/<name>/ # OpenCode
|
||||||
|
|
||||||
|
|
||||||
|
~/proj/skills/skills/<name>/ # Development (pi-only)
|
||||||
|
│
|
||||||
|
│ deploy-skill.sh <name> --pi-only
|
||||||
|
▼
|
||||||
|
~/proj/dotfiles/pi/skills/<name>/ # Nix source (pi-only)
|
||||||
|
│
|
||||||
|
│ home-manager rebuild
|
||||||
|
▼
|
||||||
|
~/.pi/agent/skills/<name>/ # Pi only
|
||||||
|
```
|
||||||
|
|
||||||
|
**Two tiers**:
|
||||||
|
- **Universal**: Deploy to all agents (`~/.claude/`, `~/.codex/`, `~/.config/opencode/`)
|
||||||
|
- **Pi-only**: Deploy to `~/.pi/agent/skills/` only (for extension-dependent skills like ralph-work-loop)
|
||||||
|
|
||||||
|
### Pi Settings
|
||||||
|
|
||||||
|
Global `~/.pi/agent/settings.json`:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"skills": {
|
||||||
|
"enableClaudeUser": true, // Universal skills (~/.claude/skills/)
|
||||||
|
"enablePiUser": true, // Pi-only skills (~/.pi/agent/skills/)
|
||||||
|
"enableCodexUser": false, // Don't double-load (Nix manages ~/.codex/)
|
||||||
|
"enableClaudeProject": true,
|
||||||
|
"enablePiProject": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Pi reads from both `~/.claude/skills/` (universal) and `~/.pi/agent/skills/` (pi-specific).
|
||||||
|
|
||||||
|
### Per-Repo Filtering
|
||||||
|
|
||||||
|
Project `.pi/settings.json`:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"skills": {
|
||||||
|
"ignoredSkills": ["nix-review", "ops-review"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Or positive filtering:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"skills": {
|
||||||
|
"includeSkills": ["worklog", "code-review", "intent", "approach", "work"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Nix Module
|
||||||
|
|
||||||
|
In `home/skills.nix` (or similar):
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
home.file = {
|
||||||
|
".claude/skills" = {
|
||||||
|
source = ./skills;
|
||||||
|
recursive = true;
|
||||||
|
};
|
||||||
|
".codex/skills" = {
|
||||||
|
source = ./skills;
|
||||||
|
recursive = true;
|
||||||
|
};
|
||||||
|
".config/opencode/skills" = {
|
||||||
|
source = ./skills;
|
||||||
|
recursive = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Risks
|
||||||
|
|
||||||
|
### Known Unknowns
|
||||||
|
|
||||||
|
- **OpenCode skill format**: Does it use the same SKILL.md format? Need to verify.
|
||||||
|
- **Codex recursive scanning**: Pi docs say it scans recursively — does Codex itself do this too?
|
||||||
|
- **Project-local skills**: Should these also be standardized, or left as-is per project?
|
||||||
|
|
||||||
|
### Failure Modes
|
||||||
|
|
||||||
|
- **Nix rebuild required**: Skills don't update until rebuild. Could forget and wonder why changes aren't visible.
|
||||||
|
- **Agent format drift**: If an agent changes its skill format, we'd need to adapt.
|
||||||
|
- **includeSkills too restrictive**: Forget to add a skill to the include list, then wonder why it's not loading.
|
||||||
|
|
||||||
|
### Blast Radius
|
||||||
|
|
||||||
|
- **Dotfiles changes**: Modifying Nix config affects all machines using these dotfiles.
|
||||||
|
- **Removing old locations**: If we delete `~/.pi/agent/skills/` contents, need to ensure pi settings are updated first.
|
||||||
|
|
||||||
|
## Phases
|
||||||
|
|
||||||
|
### Phase 1: Consolidate to Dotfiles
|
||||||
|
- Move all global skills to `~/proj/dotfiles/skills/`
|
||||||
|
- Update Nix to deploy to all agent locations
|
||||||
|
- Update pi settings to read from `~/.claude/skills/` only
|
||||||
|
|
||||||
|
### Phase 2: Clean Up Old Locations
|
||||||
|
- Remove skills from `~/.codex/skills/`, `~/.pi/agent/skills/` (Nix now manages these)
|
||||||
|
- Verify all agents still work
|
||||||
|
|
||||||
|
### Phase 3: Per-Repo Filtering
|
||||||
|
- Add `.pi/settings.json` to repos that need filtering
|
||||||
|
- Document the pattern for future repos
|
||||||
42
docs/intent/2026-01-25-skill-organization.md
Normal file
42
docs/intent/2026-01-25-skill-organization.md
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
# Intent: Skill Organization Across Agents
|
||||||
|
|
||||||
|
## Motivation
|
||||||
|
|
||||||
|
Skills are scattered across multiple directories (`~/.codex/skills/`, `~/.claude/skills/`, `~/.pi/agent/skills/`), leading to duplication and drift. Some repos load skills they don't need. We want a single source of truth with clean deployment to all agents.
|
||||||
|
|
||||||
|
## Need
|
||||||
|
|
||||||
|
A maintainable system for:
|
||||||
|
1. Developing skills in one place
|
||||||
|
2. Deploying to all agent locations (pi, Claude Code, OpenCode, Codex)
|
||||||
|
3. Filtering which skills load in which repos
|
||||||
|
4. Keeping compatibility with agents we might use later
|
||||||
|
|
||||||
|
## Use-Cases
|
||||||
|
|
||||||
|
- **Skill development**: Edit a skill in `~/proj/skills/`, run deploy, all agents pick it up after Nix rebuild.
|
||||||
|
- **Per-repo filtering**: Working in a Python project — don't load `nix-review`. Working in a Nix project — don't load `python-lint`.
|
||||||
|
- **Agent compatibility**: Switch to Claude Code for a session — same skills available, same behavior.
|
||||||
|
- **Avoiding drift**: Fix a bug in `worklog` skill — fix it once, deployed everywhere. No stale copies in random directories.
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
|
||||||
|
- Single source of truth for global skills (in dotfiles, managed by Nix)
|
||||||
|
- All agents (pi, Claude Code, OpenCode, Codex) load skills from their expected locations
|
||||||
|
- Per-repo skill filtering works (via pi settings or project config)
|
||||||
|
- No duplicate skill directories to maintain
|
||||||
|
- Development workflow: edit in skills repo → deploy → Nix rebuild → available everywhere
|
||||||
|
|
||||||
|
## Constraints
|
||||||
|
|
||||||
|
- Must work with Nix/home-manager deployment (no direnv, no runtime symlink management)
|
||||||
|
- Skills must remain compatible with Agent Skills standard (SKILL.md format)
|
||||||
|
- Pi is primary agent, but others must keep working
|
||||||
|
- Extensions (TypeScript) are pi-only, separate concern for now
|
||||||
|
|
||||||
|
## Anti-Goals
|
||||||
|
|
||||||
|
- **Not changing skill format**: Skills stay as SKILL.md + scripts, no new abstraction
|
||||||
|
- **Not building a skill manager tool**: Use Nix for deployment, not a custom CLI
|
||||||
|
- **Not per-file filtering**: Filtering is per-skill, not per-file within a skill
|
||||||
|
- **Not solving extension organization**: Extensions stay in `~/.pi/agent/extensions/`, address later if needed
|
||||||
74
docs/work/2026-01-25-skill-organization.md
Normal file
74
docs/work/2026-01-25-skill-organization.md
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
# Work: Skill Organization Across Agents
|
||||||
|
|
||||||
|
## Intent
|
||||||
|
Link to: [docs/intent/2026-01-25-skill-organization.md](../intent/2026-01-25-skill-organization.md)
|
||||||
|
|
||||||
|
## Approach
|
||||||
|
Link to: [docs/approach/2026-01-25-skill-organization.md](../approach/2026-01-25-skill-organization.md)
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
### Phase 1: Consolidate to Dotfiles
|
||||||
|
|
||||||
|
- [x] **W001**: Inventory current skills across all locations
|
||||||
|
- Verification: `find ~/.codex/skills ~/.claude/skills ~/.pi/agent/skills -name "SKILL.md" 2>/dev/null | wc -l` returns count
|
||||||
|
|
||||||
|
- [x] **W002**: Create `~/proj/dotfiles/skills/` directory structure
|
||||||
|
- Verification: SKIP — using existing ai-skills module, skills sourced from this repo
|
||||||
|
|
||||||
|
- [x] **W003**: Create `~/proj/dotfiles/pi/skills/` for pi-only skills
|
||||||
|
- Verification: SKIP — piSkills added to ai-skills module, ralph-work-loop in this repo
|
||||||
|
|
||||||
|
- [x] **W004**: Copy universal skills to dotfiles/skills/
|
||||||
|
- Verification: SKIP — skills already in ~/proj/skills/skills/, ai-skills module deploys them
|
||||||
|
|
||||||
|
- [x] **W005**: Copy pi-only skills to dotfiles/pi/skills/
|
||||||
|
- Verification: `ls skills/ralph-work-loop/SKILL.md` exists in this repo
|
||||||
|
|
||||||
|
- [x] **W006**: Create/update Nix module to deploy skills to all agent locations
|
||||||
|
- Verification: Added piSkills option to modules/ai-skills.nix
|
||||||
|
|
||||||
|
- [x] **W007**: Update pi settings to use correct sources
|
||||||
|
- Verification: `cat ~/.pi/agent/settings.json | jq '.skills'` shows correct flags
|
||||||
|
|
||||||
|
- [ ] **W008**: Nix rebuild and verify skills appear in all locations
|
||||||
|
- Verification: `ls ~/.claude/skills ~/.codex/skills ~/.config/opencode/skills ~/.pi/agent/skills` all populated
|
||||||
|
|
||||||
|
### Phase 2: Clean Up Old Locations
|
||||||
|
|
||||||
|
- [ ] **W009**: Remove manually-managed skills from ~/.codex/skills/ (Nix now manages)
|
||||||
|
- Verification: Skills in ~/.codex/skills/ match dotfiles exactly (no extras)
|
||||||
|
|
||||||
|
- [ ] **W010**: Remove manually-managed skills from ~/.pi/agent/skills/ (except pi-only)
|
||||||
|
- Verification: Only ralph-work-loop in ~/.pi/agent/skills/
|
||||||
|
|
||||||
|
- [ ] **W011**: Remove duplicate skills from project-local directories (talu, etc.)
|
||||||
|
- Verification: `ls ~/proj/talu/.claude/skills/` shows only project-specific skills (if any)
|
||||||
|
|
||||||
|
### Phase 3: Update deploy-skill.sh
|
||||||
|
|
||||||
|
- [ ] **W012**: Update deploy-skill.sh to support --pi-only flag
|
||||||
|
- Verification: `./bin/deploy-skill.sh --help` shows --pi-only option
|
||||||
|
|
||||||
|
- [ ] **W013**: Update deploy-skill.sh to copy to correct dotfiles location
|
||||||
|
- Verification: `./bin/deploy-skill.sh worklog` copies to `~/proj/dotfiles/skills/worklog/`
|
||||||
|
|
||||||
|
- [ ] **W014**: Test end-to-end: create skill, deploy, rebuild, verify in agents
|
||||||
|
- Verification: Create test-skill, deploy, rebuild, `ls ~/.claude/skills/test-skill/SKILL.md` exists
|
||||||
|
|
||||||
|
## Verification Evidence
|
||||||
|
|
||||||
|
- (2026-01-25) W001: Inventoried 4 locations, found existing ai-skills Nix module already handles deployment
|
||||||
|
- (2026-01-25) W002-W005: SKIP — infrastructure already exists in this repo + ai-skills module
|
||||||
|
- (2026-01-25) W006: Added piSkills option to modules/ai-skills.nix
|
||||||
|
- (2026-01-25) Copied ralph-work-loop to skills/ directory
|
||||||
|
- (2026-01-25) Updated skills.nix registry
|
||||||
|
- (2026-01-25) Updated ~/proj/dotfiles/home/claude.nix with full skill lists + piSkills
|
||||||
|
- (2026-01-25) Removed manual nix-review deployments from codex.nix, opencode.nix, gemini.nix (now managed by ai-skills)
|
||||||
|
- (2026-01-25) W007: Added settings.json to ~/proj/dotfiles/home/pi.nix with skill source config
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Universal skills: worklog, screenshot-latest, orch, playwright-visit, code-review, ops-review, nix-review, hq, niri-window-capture, intent, approach, work
|
||||||
|
- Pi-only skills: ralph-work-loop
|
||||||
|
- Need to check what's currently in each location before migrating
|
||||||
|
|
@ -53,6 +53,13 @@ in {
|
||||||
example = [ "worklog" "web-search" ];
|
example = [ "worklog" "web-search" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
piSkills = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
description = "Skills to deploy to Pi (~/.pi/agent/skills/). For pi-only skills that depend on extensions. ${skillsList}";
|
||||||
|
example = [ "ralph-work-loop" ];
|
||||||
|
};
|
||||||
|
|
||||||
# Lenses for orch multi-model review
|
# Lenses for orch multi-model review
|
||||||
enableLenses = mkOption {
|
enableLenses = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
|
|
@ -116,6 +123,19 @@ in {
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
|
# Pi skills (pi-only, extension-dependent)
|
||||||
|
(mkIf (cfg.piSkills != []) (
|
||||||
|
builtins.listToAttrs (
|
||||||
|
map (skillName: {
|
||||||
|
name = ".pi/agent/skills/${skillName}";
|
||||||
|
value = {
|
||||||
|
source = "${cfg.skillsPath}/${skillName}";
|
||||||
|
recursive = true;
|
||||||
|
};
|
||||||
|
}) cfg.piSkills
|
||||||
|
)
|
||||||
|
))
|
||||||
|
|
||||||
# Lenses for orch (separate subdirectories per skill)
|
# Lenses for orch (separate subdirectories per skill)
|
||||||
(mkIf cfg.enableLenses {
|
(mkIf cfg.enableLenses {
|
||||||
".config/lenses/code" = {
|
".config/lenses/code" = {
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,19 @@
|
||||||
handoff = "Create structured handoff summaries";
|
handoff = "Create structured handoff summaries";
|
||||||
intent = "Capture the volition and problem space (The Why)";
|
intent = "Capture the volition and problem space (The Why)";
|
||||||
niri-window-capture = "Invisibly capture window screenshots";
|
niri-window-capture = "Invisibly capture window screenshots";
|
||||||
|
nix-review = "Nix-focused infrastructure review";
|
||||||
ops-review = "Multi-lens ops/infrastructure review";
|
ops-review = "Multi-lens ops/infrastructure review";
|
||||||
orch = "Orchestration and consensus skill";
|
orch = "Orchestration and consensus skill";
|
||||||
brave-search = "Web search via Brave API";
|
brave-search = "Web search via Brave API";
|
||||||
browser-tools = "Interactive browser automation via CDP";
|
browser-tools = "Interactive browser automation via CDP";
|
||||||
playwright-visit = "Browser automation and content extraction";
|
playwright-visit = "Browser automation and content extraction";
|
||||||
|
ralph-work-loop = "Run iterative Work-phase execution via Ralph extension (pi-only)";
|
||||||
review-gate = "Quality gate for agent work";
|
review-gate = "Quality gate for agent work";
|
||||||
screenshot-latest = "Find latest screenshots";
|
screenshot-latest = "Find latest screenshots";
|
||||||
spec-review = "Technical specification review";
|
spec-review = "Technical specification review";
|
||||||
tufte-press = "Generate study card JSON";
|
tufte-press = "Generate study card JSON";
|
||||||
test-review = "Audit test quality for flakiness, tautologies, and anti-patterns";
|
test-review = "Audit test quality for flakiness, tautologies, and anti-patterns";
|
||||||
|
ui-query = "Query UI elements via accessibility APIs";
|
||||||
verify-work = "The Gatekeeper: Run project build/tests before claiming success";
|
verify-work = "The Gatekeeper: Run project build/tests before claiming success";
|
||||||
work = "Execute and verify the implementation (The Do)";
|
work = "Execute and verify the implementation (The Do)";
|
||||||
worklog = "Create structured worklogs";
|
worklog = "Create structured worklogs";
|
||||||
|
|
|
||||||
15
skills/ralph-work-loop/README.md
Normal file
15
skills/ralph-work-loop/README.md
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
# Ralph Work Loop Skill
|
||||||
|
|
||||||
|
Runs the Ralph Wiggum loop on an existing Work document.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
/ralph start docs/work/<work-doc>.md
|
||||||
|
```
|
||||||
|
|
||||||
|
If you don't know the work doc, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./.pi/skills/ralph-work-loop/scripts/find-latest-work.sh
|
||||||
|
```
|
||||||
51
skills/ralph-work-loop/SKILL.md
Normal file
51
skills/ralph-work-loop/SKILL.md
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
---
|
||||||
|
name: ralph-work-loop
|
||||||
|
description: Start or resume a Ralph Wiggum loop on an existing Work document (docs/work/*.md). Use when the user asks to "use ralph" on a Work doc or to run iterative Work-phase execution.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Ralph Work Loop
|
||||||
|
|
||||||
|
Use this skill to run the Ralph Wiggum loop **after** a Work document exists.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Ralph extension installed: `.pi/extensions/ralph-wiggum/index.ts`
|
||||||
|
- Work document already created in `docs/work/`
|
||||||
|
|
||||||
|
## Process
|
||||||
|
|
||||||
|
1. **Validate the Work doc**:
|
||||||
|
- Check required sections: Intent link, Approach link, Checklist, Verification commands, Evidence section
|
||||||
|
- Each checklist item needs a verification command
|
||||||
|
- See the `work` skill for full validation checklist
|
||||||
|
- Fix any issues before starting the loop
|
||||||
|
|
||||||
|
2. **Locate the Work doc**:
|
||||||
|
- If user provides a path, use it.
|
||||||
|
- Otherwise run:
|
||||||
|
```bash
|
||||||
|
./.pi/skills/ralph-work-loop/scripts/find-latest-work.sh
|
||||||
|
```
|
||||||
|
- If multiple candidates are relevant, list them and ask the user to choose.
|
||||||
|
|
||||||
|
3. **Start the loop**:
|
||||||
|
```
|
||||||
|
/ralph start <work-doc-path>
|
||||||
|
```
|
||||||
|
Optional flags (ask user if they care):
|
||||||
|
- `--items-per-iteration N`
|
||||||
|
- `--reflect-every N`
|
||||||
|
- `--max-iterations N`
|
||||||
|
|
||||||
|
4. **Monitor or resume**:
|
||||||
|
- ` /ralph status` to show active loops
|
||||||
|
- ` /ralph resume <name>` to continue paused loop
|
||||||
|
|
||||||
|
5. **Stop**:
|
||||||
|
- Press `ESC` to pause
|
||||||
|
- ` /ralph-stop` when idle to end the loop
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- The loop enforces the **Intent → Approach → Work** dialect and requires verification evidence for completed items.
|
||||||
|
- Use `/ralph start <path>` to point directly to an existing Work doc.
|
||||||
25
skills/ralph-work-loop/scripts/find-latest-work.sh
Executable file
25
skills/ralph-work-loop/scripts/find-latest-work.sh
Executable file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
skill_dir="$(cd "${script_dir}/.." && pwd)"
|
||||||
|
root_dir="$(cd "${skill_dir}/../../.." && pwd)"
|
||||||
|
|
||||||
|
work_dir="${root_dir}/docs/work"
|
||||||
|
if [[ ! -d "${work_dir}" ]]; then
|
||||||
|
echo "Error: docs/work not found at ${work_dir}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
latest_file=""
|
||||||
|
if compgen -G "${work_dir}/*.md" > /dev/null; then
|
||||||
|
latest_file="$(ls -t "${work_dir}"/*.md | head -n 1)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${latest_file}" ]]; then
|
||||||
|
echo "Error: no Work docs found in ${work_dir}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
relative_path="${latest_file#"${root_dir}/"}"
|
||||||
|
echo "${relative_path}"
|
||||||
Loading…
Reference in a new issue