Skip to content

chore: fix local-hosting discovery and simplify SKILL.md generation#2182

Merged
marcusquinn merged 2 commits intomainfrom
chore/fix-local-hosting-discovery-and-skills-generation
Feb 23, 2026
Merged

chore: fix local-hosting discovery and simplify SKILL.md generation#2182
marcusquinn merged 2 commits intomainfrom
chore/fix-local-hosting-discovery-and-skills-generation

Conversation

@marcusquinn
Copy link
Owner

@marcusquinn marcusquinn commented Feb 23, 2026

Summary

  • Domain Index fix: Added "Local Development" row to AGENTS.md Domain Index — local-hosting.md was buried under "Infrastructure", making it undiscoverable when users mention ".local domains"
  • Merge localhost.md: Reduced 423-line legacy localhost.md to a 17-line redirect stub pointing to local-hosting.md (single source of truth). Moved unique LocalWP MCP commands into local-hosting.md.
  • generate-skills.sh Pattern 3: New pattern generates SKILL.md stubs for standalone .md files without matching folders (e.g., local-hosting.md previously got no stub, causing discovery gaps in tools using the Agent Skills standard)
  • Pure pointer stubs: Removed inlined subskill lists from all SKILL.md generation patterns — stubs now contain only frontmatter + a link to the source .md file. Eliminates stale content that caused a session to miss local-hosting.md entirely.

Context

Another session asked to "setup .local hosting" and the agent didn't find local-hosting.md because:

  1. Domain Index listed it under "Infrastructure" (not intuitive for ".local")
  2. Two files (localhost.md + local-hosting.md) for the same domain caused confusion
  3. generate-skills.sh didn't create a SKILL.md stub for standalone files without matching folders
  4. The hosting SKILL.md had a stale subskill list that showed localhost but not local-hosting

Testing

  • bash -n syntax check: pass
  • shellcheck: clean (only SC1091 for sourced file, expected)
  • markdownlint: clean on all 3 changed .md files
  • generate-skills.sh --clean && generate-skills.sh: generates 832 stubs (up from 143), all pure pointers
  • Verified local-hosting/SKILL.md is now generated with correct description

Summary by CodeRabbit

  • Documentation

    • Reorganized and consolidated local hosting docs; localhost now redirects to local-hosting with clearer guidance on .local, browser vs CLI resolution, and updated examples.
    • Clarified MCP docs and header formatting.
  • New Features

    • Added test-mcp and mcp-query commands for testing MCP connections and querying WordPress databases.
  • Behavior Changes

    • Adding a domain now always updates /etc/hosts; dnsmasq remains for CLI wildcard resolution.
  • Chores

    • Documentation build now generates simpler, pointer-style skill files.

- Add 'Local Development' row to Domain Index in AGENTS.md (was buried under Infrastructure)
- Merge localhost.md content into local-hosting.md, reduce localhost.md to redirect stub
- Add LocalWP MCP commands (test-mcp, mcp-query) to local-hosting.md legacy CLI section
- Fix generate-skills.sh: add Pattern 3 for standalone .md files without matching folders
  (e.g., local-hosting.md now gets a SKILL.md stub — previously missed)
- Fix generate-skills.sh: remove inlined subskill lists from all patterns, keep stubs as
  pure pointers to avoid stale content that caused discovery failures
@gemini-code-assist
Copy link

Summary of Changes

Hello @marcusquinn, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refines the agent skill discovery and documentation structure. The primary goal is to enhance the user experience by making local development information more accessible and consolidating related content into a single, authoritative source. It also streamlines the automated generation of skill documentation, ensuring that all relevant markdown files are properly indexed without redundant or outdated information.

Highlights

  • Improved Local Hosting Discoverability: The local-hosting.md entry was moved from 'Infrastructure' to a new 'Local Development' category in AGENTS.md, making it easier to find for users searching for local development solutions.
  • Consolidated Localhost Documentation: The extensive localhost.md file was reduced to a 17-line redirect stub, pointing to local-hosting.md as the single source of truth. Unique LocalWP MCP commands from the old localhost.md were integrated into local-hosting.md.
  • Enhanced SKILL.md Generation: The generate-skills.sh script was updated with a new pattern (Pattern 3) to create SKILL.md stubs for standalone .md files that previously lacked them, addressing discovery gaps. Additionally, all SKILL.md generation patterns now produce 'pure pointer' stubs, removing inlined subskill lists to prevent stale content.
Changelog
  • .agents/AGENTS.md
    • Moved services/hosting/local-hosting.md from the 'Infrastructure' category to a newly created 'Local Development' category.
  • .agents/scripts/generate-skills.sh
    • Refactored generate_folder_skill to remove inlined subskill lists, creating pure pointer SKILL.md files.
    • Modified Pattern 2 for nested folders to also generate pure pointer SKILL.md files without inlined subskill lists.
    • Introduced a new Pattern 3 to generate SKILL.md stubs for standalone .md files in nested directories that do not have a matching folder, improving skill discoverability.
    • Added logic to Pattern 3 to skip specific files (SKILL.md, AGENTS.md, README.md) and files in special top-level directories.
    • Adjusted indentation for consistency across the script.
  • .agents/services/hosting/local-hosting.md
    • Added test-mcp and mcp-query commands to the LocalWP MCP section.
    • Updated the 'Legacy Context' section to reflect that localhost.md is now a redirect stub and that legacy localhost-helper.sh commands are documented in this file.
  • .agents/services/hosting/localhost.md
    • Transformed the file into a brief redirect stub, pointing to local-hosting.md.
    • Removed extensive legacy documentation and quick reference sections.
    • Updated the frontmatter description to indicate its redirect status.
Activity
  • The pull request was created by marcusquinn to address issues with local-hosting discovery and simplify SKILL.md generation.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

Walkthrough

Documentation and tooling updates: AGENTS.md adds a Local Development row and reorganizes hosting entries; skill-generation script now emits pointer-only SKILL.md files; localhost.md redirected into local-hosting.md which gained CLI-focused DNS/hosts guidance, MCP test/query commands, and related helper-script messaging updates.

Changes

Cohort / File(s) Summary
Documentation Index
\.agents/AGENTS.md
Added a Local Development row to the Domain Index and moved hosting-related entry out of Infrastructure.
Skill Generation Script
\.agents/scripts/generate-skills.sh
Refactored SKILL.md generation to a pointer-only model, added frontmatter quote-stripping, reorganized extraction and generation helpers, and simplified logging/formatting.
Local Hosting Docs
\.agents/services/hosting/local-hosting.md
Consolidated localhost content here; clarified DNS resolution (.local mDNS vs hosts vs dnsmasq), updated init/add flows, added LocalWP MCP test-mcp and mcp-query commands, and adjusted headers/examples.
Localhost Redirect
\.agents/services/hosting/localhost.md
Replaced detailed legacy doc with a redirect/stub pointing to local-hosting.md and a short summary of highlights.
Localdev Helper Script
\.agents/scripts/localdev-helper.sh
Updated help/init messaging and comments to require /etc/hosts entries for browser resolution, clarified dnsmasq vs browser behavior, and changed add behavior to always write /etc/hosts (no signature-level API changes).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

✨ Hosts and skills rearranged with care,
Docs point the way and scripts now declare,
Localhost moved to a single place,
MCP tests join the CLI race,
Small tidy steps — a cleaner dev affair 🛠️

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 70.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the two main changes: fixing local-hosting discovery via the Domain Index and simplifying SKILL.md generation to pure pointers.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/fix-local-hosting-discovery-and-skills-generation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 40 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Mon Feb 23 00:29:09 UTC 2026: Code review monitoring started
Mon Feb 23 00:29:10 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 40

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 40
  • VULNERABILITIES: 0

Generated on: Mon Feb 23 00:29:12 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request effectively addresses the discoverability issues of local-hosting.md by reclassifying it in the AGENTS.md Domain Index and simplifying SKILL.md generation. The consolidation of localhost.md into a redirect stub is a good step towards maintaining a single source of truth, aligning with the rule for a tiered documentation structure. The new Pattern 3 in generate-skills.sh correctly handles standalone .md files, improving the overall skill discovery mechanism. The removal of inlined subskill lists from SKILL.md stubs also contributes to better maintainability and prevents stale content. Overall, these changes enhance the clarity and maintainability of the agent documentation. The changes to indentation in generate-skills.sh are noted for consistency.

Comment on lines +101 to +102
| Local Development | `services/hosting/local-hosting.md` |
| Infrastructure | `tools/infrastructure/cloud-gpu.md`, `tools/containers/orbstack.md`, `tools/containers/remote-dispatch.md` |

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The change to move local-hosting.md from 'Infrastructure' to a new 'Local Development' category is a significant improvement for discoverability. This aligns with the pull request description's goal of making the file more intuitive to find when users search for '.local domains'.

References
  1. Maintain a tiered documentation structure with a concise core file and detailed reference files. Avoid adding extensive details to the core file if they are already present or better suited for a reference file.

Comment on lines +37 to +50
case $1 in
--dry-run)
DRY_RUN=true
shift
;;
--clean)
CLEAN=true
shift
;;
*)
echo -e "${RED}Unknown option: $1${NC}"
exit 1
;;
esac

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The indentation for the case statement has changed. While functional, it deviates from the previous style. For consistency, it's better to maintain the original indentation style.

Suggested change
case $1 in
--dry-run)
DRY_RUN=true
shift
;;
--clean)
CLEAN=true
shift
;;
*)
echo -e "${RED}Unknown option: $1${NC}"
exit 1
;;
esac
case $1 in
--dry-run)
DRY_RUN=true
shift
;;
--clean)
CLEAN=true
shift
;;
*)
echo -e "${RED}Unknown option: $1${NC}"
exit 1
;;
esac

Comment on lines +58 to 60
echo -e "${BLUE}$1${NC}"
return 0
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The indentation for the log_info function has changed. For consistency, it's better to maintain the original indentation style.

Suggested change
echo -e "${BLUE}$1${NC}"
return 0
}
log_info() {
echo -e "${BLUE}$1${NC}"
return 0
}

Comment on lines 62 to +64
log_success() {
echo -e "${GREEN}✓${NC} $1"
return 0
echo -e "${GREEN}✓${NC} $1"
return 0

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The indentation for the log_success function has changed. For consistency, it's better to maintain the original indentation style.

Suggested change
log_success() {
echo -e "${GREEN}${NC} $1"
return 0
echo -e "${GREEN}${NC} $1"
return 0
log_success() {
echo -e "${GREEN}${NC} $1"
return 0
}

Comment on lines 66 to +68

log_warning() {
echo -e "${YELLOW}⚠${NC} $1"
return 0
echo -e "${YELLOW}⚠${NC} $1"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The indentation for the log_warning function has changed. For consistency, it's better to maintain the original indentation style.

Suggested change
log_warning() {
echo -e "${YELLOW}${NC} $1"
return 0
echo -e "${YELLOW}${NC} $1"
log_warning() {
echo -e "${YELLOW}${NC} $1"
return 0
}

Comment on lines +364 to +365
log_warning ""
log_warning "This was a dry run. Run without --dry-run to generate files."

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The indentation for the log_warning statements has changed. For consistency, it's better to maintain the original indentation style.

Suggested change
log_warning ""
log_warning "This was a dry run. Run without --dry-run to generate files."
log_warning ""
log_warning "This was a dry run. Run without --dry-run to generate files."

Comment on lines +262 to +266
# LocalWP MCP (port 8085)
localhost-helper.sh start-mcp # Start LocalWP MCP server
localhost-helper.sh stop-mcp # Stop LocalWP MCP server
localhost-helper.sh test-mcp # Test MCP connection
localhost-helper.sh mcp-query "<sql>" # Query WordPress database via MCP

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The addition of test-mcp and mcp-query commands to the LocalWP MCP section is a good enhancement, providing more complete documentation for LocalWP integration. This directly addresses the need to move unique LocalWP MCP commands into local-hosting.md as mentioned in the PR summary.

References
  1. For clarity in documentation, restore key helper scripts and commands to domain index entries if they are frequently used, even if detailed documentation exists elsewhere.

Comment on lines +761 to +763
The `localhost.md` file in this directory is a redirect stub pointing here. The legacy `localhost-helper.sh` commands are documented in the CLI Reference section above.

Key differences:
Key differences between legacy and current:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The updated description for localhost.md clarifies its role as a redirect stub and correctly points to local-hosting.md as the single source of truth. This improves clarity and helps users find the most up-to-date information.

References
  1. Maintain a tiered documentation structure with a concise core file and detailed reference files. Avoid adding extensive details to the core file if they are already present or better suited for a reference file.

Comment on lines +2 to 4
description: "Redirect: see local-hosting.md for all local development hosting"
mode: subagent
tools:
read: true
write: true
edit: true
bash: true
glob: true
grep: true
webfetch: false
---

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The removal of the tools frontmatter block is appropriate for a redirect stub, as it simplifies the file and reinforces its role as a pointer to local-hosting.md. The description update is also clear and concise.

References
  1. Maintain a tiered documentation structure with a concise core file and detailed reference files. Avoid adding extensive details to the core file if they are already present or better suited for a reference file.

Comment on lines +6 to +17
# Localhost — Redirected

# Localhost Development Environment Guide
This file has been merged into [`local-hosting.md`](local-hosting.md), which covers both the current `localdev-helper.sh` system and the legacy `localhost-helper.sh` commands.

<!-- AI-CONTEXT-START -->
Read `local-hosting.md` for:

## Quick Reference

- **Type**: Local development environment management
- **Config**: `configs/localhost-config.json`
- **Commands**: `localhost-helper.sh [check-port|find-port|list-ports|kill-port|generate-cert|setup-dns|setup-proxy|create-app|start-mcp] [args]`
- **LocalWP**: Sites in `/Users/username/Local Sites`, MCP on port 8085
- **SSL**: `generate-cert`, `setup-proxy` for local HTTPS via Traefik
- **Ports**: `check-port`, `find-port`, `list-ports`, `kill-port`

**CRITICAL: Why .local + SSL + Port Checking?**

| Problem | Solution | Why It Matters |
|---------|----------|----------------|
| Port conflicts | `check-port`, `find-port` | Avoids "address already in use" errors |
| Password managers don't work | SSL via Traefik proxy | 1Password, Bitwarden require HTTPS to autofill |
| Inconsistent URLs | `.local` domains | `myapp.local` instead of `localhost:3847` |
| Browser security warnings | `mkcert` trusted certs | No "proceed anyway" clicks |

**Standard Setup Pattern:**

```bash
# 1. Check port availability first
localhost-helper.sh check-port 3000

# 2. If conflict, find next available (returns e.g., 3001)
available_port=$(localhost-helper.sh find-port 3000)

# 3. Create app with .local domain + SSL using available port
localhost-helper.sh create-app myapp myapp.local "$available_port" true docker
```

<!-- AI-CONTEXT-END -->

Localhost development provides local development capabilities with .local domain support, perfect for development workflows and testing environments.

## Why .local Domains + SSL + Port Management?

### The Problem with `localhost:port`

Traditional local development uses URLs like `http://localhost:3000`. This causes several issues:

1. **Password managers don't work** - 1Password, Bitwarden, and other password managers require HTTPS to autofill credentials. They won't save or fill passwords on `http://` URLs for security reasons.

2. **Port conflicts are common** - Multiple projects fighting for port 3000, 8080, etc. leads to "EADDRINUSE" errors and manual port hunting.

3. **Inconsistent URLs** - Remembering which project is on which port is cognitive overhead. Was it 3000 or 3001?

4. **No SSL testing** - Can't test SSL-specific features, secure cookies, or HSTS locally.

### The Solution: .local + SSL + Port Checking

| Component | Tool | Purpose |
|-----------|------|---------|
| `.local` domains | dnsmasq | Consistent, memorable URLs (`myapp.local`) |
| SSL certificates | mkcert | Browser-trusted HTTPS locally |
| Reverse proxy | Traefik | Routes `.local` domains to correct ports |
| Port management | localhost-helper.sh | Avoids conflicts, finds available ports |

### Standard Workflow

**Before starting any local service:**

```bash
# 1. Check if desired port is available
~/.aidevops/agents/scripts/localhost-helper.sh check-port 3000

# 2. If in use, find next available
available_port=$(~/.aidevops/agents/scripts/localhost-helper.sh find-port 3000)
echo "Using port: $available_port"

# 3. Create app with .local domain + SSL using available port
~/.aidevops/agents/scripts/localhost-helper.sh create-app myapp myapp.local "$available_port" true docker
```

**Result:** Access your app at `https://myapp.local` with:
- Password manager autofill working
- No port conflicts
- Browser-trusted SSL
- Consistent URL across sessions

## Provider Overview

### **Localhost Characteristics:**

- **Service Type**: Local development environment management
- **Domain Support**: .local domain resolution and management
- **Development Tools**: Integration with local development stacks
- **SSL Support**: Local SSL certificate management
- **Port Management**: Local port allocation and management
- **Service Discovery**: Local service discovery and routing

### **Best Use Cases:**

- **Local WordPress development** with LocalWP integration
- **Microservices development** with local service discovery
- **API development and testing** with local endpoints
- **Frontend development** with local backend services
- **SSL testing** with local certificate management
- **Development environment isolation** and management

## 🔧 **Configuration**

### **Setup Configuration:**

```bash
# Copy template
cp configs/localhost-config.json.txt configs/localhost-config.json

# Edit with your local development setup
```

### **Configuration Structure:**

```json
{
"environments": {
"wordpress": {
"type": "localwp",
"sites_path": "/Users/username/Local Sites",
"description": "LocalWP WordPress development",
"mcp_enabled": true,
"mcp_port": 3001
},
"nodejs": {
"type": "nodejs",
"projects_path": "/Users/username/Projects",
"description": "Node.js development projects",
"default_port": 3000
},
"docker": {
"type": "docker",
"compose_path": "/Users/username/Docker",
"description": "Docker development environments",
"network": "dev-network"
}
}
}
```

### **Local Domain Setup:**

1. **Configure local DNS** resolution for .local domains
2. **Set up SSL certificates** for HTTPS development
3. **Configure port forwarding** for service access
4. **Set up service discovery** for microservices
5. **Test local domain** resolution

## 🚀 **Usage Examples**

### **Basic Commands:**

```bash
# List local environments
./.agents/scripts/localhost-helper.sh environments

# Start local environment
./.agents/scripts/localhost-helper.sh start wordpress

# Stop local environment
./.agents/scripts/localhost-helper.sh stop wordpress

# Get environment status
./.agents/scripts/localhost-helper.sh status wordpress
```

### **LocalWP Integration:**

```bash
# List LocalWP sites
./.agents/scripts/localhost-helper.sh localwp-sites

# Start LocalWP site
./.agents/scripts/localhost-helper.sh start-site mysite.local

# Stop LocalWP site
./.agents/scripts/localhost-helper.sh stop-site mysite.local

# Get site info
./.agents/scripts/localhost-helper.sh site-info mysite.local

# Start MCP server for LocalWP
./.agents/scripts/localhost-helper.sh start-mcp
```

### **SSL Management:**

```bash
# Generate local SSL certificate
./.agents/scripts/localhost-helper.sh generate-ssl mysite.local

# Install SSL certificate
./.agents/scripts/localhost-helper.sh install-ssl mysite.local

# List SSL certificates
./.agents/scripts/localhost-helper.sh list-ssl

# Renew SSL certificate
./.agents/scripts/localhost-helper.sh renew-ssl mysite.local
```

### **Port Management:**

```bash
# List active ports
./.agents/scripts/localhost-helper.sh list-ports

# Check port availability
./.agents/scripts/localhost-helper.sh check-port 3000

# Kill process on port
./.agents/scripts/localhost-helper.sh kill-port 3000

# Forward port
./.agents/scripts/localhost-helper.sh forward-port 3000 8080
```

## 🛡️ **Security Best Practices**

### **Local Development Security:**

- **Isolated environments**: Keep development environments isolated
- **SSL certificates**: Use valid SSL certificates for HTTPS testing
- **Access control**: Limit access to development services
- **Data protection**: Protect sensitive development data
- **Network isolation**: Use isolated networks for development

### **SSL Certificate Management:**

```bash
# Generate development CA
./.agents/scripts/localhost-helper.sh generate-ca

# Create site certificate
./.agents/scripts/localhost-helper.sh create-cert mysite.local

# Trust certificate in system
./.agents/scripts/localhost-helper.sh trust-cert mysite.local

# Verify certificate
./.agents/scripts/localhost-helper.sh verify-cert mysite.local
```

## 🔍 **Troubleshooting**

### **Common Issues:**

#### **Domain Resolution Issues:**

```bash
# Check DNS resolution
nslookup mysite.local
dig mysite.local

# Verify hosts file
cat /etc/hosts | grep mysite.local

# Test local connectivity
ping mysite.local
```

#### **SSL Certificate Issues:**

```bash
# Check certificate validity
openssl x509 -in cert.pem -text -noout

# Verify certificate chain
./.agents/scripts/localhost-helper.sh verify-chain mysite.local

# Regenerate certificate
./.agents/scripts/localhost-helper.sh regenerate-ssl mysite.local
```

#### **Port Conflicts:**

```bash
# Find process using port
lsof -i :3000
netstat -tulpn | grep :3000

# Kill conflicting process
./.agents/scripts/localhost-helper.sh kill-port 3000

# Use alternative port
./.agents/scripts/localhost-helper.sh start-on-port mysite.local 3001
```

## 📊 **Development Workflow**

### **Environment Management:**

```bash
# Start development stack
./.agents/scripts/localhost-helper.sh start-stack development

# Stop development stack
./.agents/scripts/localhost-helper.sh stop-stack development

# Restart services
./.agents/scripts/localhost-helper.sh restart-services

# Check service health
./.agents/scripts/localhost-helper.sh health-check
```

### **Project Management:**

```bash
# Create new project
./.agents/scripts/localhost-helper.sh create-project myproject

# Clone project template
./.agents/scripts/localhost-helper.sh clone-template react-app myproject

# Set up project environment
./.agents/scripts/localhost-helper.sh setup-env myproject

# Start project services
./.agents/scripts/localhost-helper.sh start-project myproject
```

## 🔄 **Integration & Automation**

### **LocalWP MCP Integration:**

```bash
# Start LocalWP MCP server
./.agents/scripts/localhost-helper.sh start-mcp

# Test MCP connection
./.agents/scripts/localhost-helper.sh test-mcp

# Query WordPress database via MCP
./.agents/scripts/localhost-helper.sh mcp-query "SELECT * FROM wp_posts LIMIT 5"

# Stop MCP server
./.agents/scripts/localhost-helper.sh stop-mcp
```

### **Docker Integration:**

```bash
# Start Docker development environment
./.agents/scripts/localhost-helper.sh docker-up myproject

# Stop Docker environment
./.agents/scripts/localhost-helper.sh docker-down myproject

# View Docker logs
./.agents/scripts/localhost-helper.sh docker-logs myproject

# Execute command in container
./.agents/scripts/localhost-helper.sh docker-exec myproject "npm test"
```

## 📚 **Best Practices**

### **Development Environment:**

1. **Consistent setup**: Use consistent development environments across team
2. **Version control**: Version control development configurations
3. **Documentation**: Document local setup procedures
4. **Automation**: Automate environment setup and teardown
5. **Testing**: Test applications in production-like environments

### **Local Domain Management:**

- **Naming conventions**: Use consistent naming for local domains
- **SSL everywhere**: Use SSL for all local development
- **Service discovery**: Implement service discovery for microservices
- **Port management**: Manage port allocation systematically
- **Environment isolation**: Isolate different project environments

### **Security Practices:**

- **Certificate management**: Properly manage local SSL certificates
- **Access control**: Limit access to development services
- **Data handling**: Handle sensitive data appropriately in development
- **Network security**: Secure local development networks
- **Regular cleanup**: Regularly clean up unused environments

## 🎯 **AI Assistant Integration**

### **Automated Development:**

- **Environment provisioning**: Automated development environment setup
- **Service orchestration**: Automated service startup and management
- **SSL management**: Automated SSL certificate generation and renewal
- **Port management**: Automated port allocation and conflict resolution
- **Health monitoring**: Automated health checks for development services

### **Development Assistance:**

- **Project scaffolding**: Automated project template generation
- **Dependency management**: Automated dependency installation and updates
- **Testing automation**: Automated test execution and reporting
- **Code quality**: Automated code quality checks and formatting
- **Documentation**: Automated documentation generation and updates

---

**Localhost development environment provides comprehensive local development capabilities with excellent integration options for modern development workflows.** 🚀
- `.local` domain setup (dnsmasq + Traefik + mkcert)
- Port registry and collision detection
- Branch subdomains for worktrees
- Shared Postgres database management
- LocalWP MCP integration
- Legacy `localhost-helper.sh` CLI reference

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This entire section has been transformed into a concise redirect stub, which is a significant improvement. It eliminates redundant information and ensures users are directed to the single source of truth (local-hosting.md), as intended by the pull request. This aligns with the goal of reducing the legacy localhost.md to a minimal redirect.

References
  1. Maintain a tiered documentation structure with a concise core file and detailed reference files. Avoid adding extensive details to the core file if they are already present or better suited for a reference file.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
.agents/services/hosting/local-hosting.md (1)

22-22: ⚠️ Potential issue | 🟡 Minor

Quick Reference omits the two new legacy commands.

Line 22 lists the legacy CLI brackets as [...|start-mcp] but doesn't include test-mcp or mcp-query that were just added to the CLI Reference block (lines 265-266).

📝 Proposed fix
-- **Legacy CLI**: `localhost-helper.sh [check-port|find-port|list-ports|kill-port|generate-cert|setup-dns|setup-proxy|create-app|start-mcp]`
+- **Legacy CLI**: `localhost-helper.sh [check-port|find-port|list-ports|kill-port|generate-cert|setup-dns|setup-proxy|create-app|start-mcp|test-mcp|mcp-query]`
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/services/hosting/local-hosting.md at line 22, The Quick Reference
legacy CLI list is missing the two new commands; update the bracketed CLI string
that currently reads `localhost-helper.sh
[check-port|find-port|list-ports|kill-port|generate-cert|setup-dns|setup-proxy|create-app|start-mcp]`
to include `test-mcp` and `mcp-query` (so it matches the CLI Reference block
where `test-mcp` and `mcp-query` were added); locate the legacy CLI entry in
local-hosting.md and append the new command names to the bracketed list.
.agents/scripts/generate-skills.sh (1)

240-241: ⚠️ Potential issue | 🟡 Minor

skipped counter is initialized but never incremented — summary always reports "Skipped: 0".

All three patterns use continue to skip items (already-existing SKILL.md, special directories, top-level files) without ever doing ((skipped++)), so the summary line:

log_info "  Skipped: $skipped (already exist or excluded)"

is always misleading. Either increment skipped at each continue site or remove the skipped line from the summary if it isn't tracked.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/generate-skills.sh around lines 240 - 241, The summary
prints "Skipped: $skipped" but skipped is never incremented; update the script
so each place that currently uses continue to skip an item (the checks for
existing "SKILL.md", the special-directory exclusion, and the top-level file
exclusion) also increments the skipped counter (use "((skipped++))" immediately
before each continue), and leave the final log_info "  Skipped: $skipped
(already exist or excluded)" as-is; alternatively, if you prefer not to track
skips, remove that log line — but the preferred fix is to increment the
"skipped" variable at each continue site.
🧹 Nitpick comments (1)
.agents/scripts/generate-skills.sh (1)

25-28: set -euo pipefail fires after source — errors in shared-constants.sh go undetected.

If shared-constants.sh emits a subshell error or exports a bad value, it runs entirely outside strict mode. Move set -euo pipefail to before the source call (or at minimum verify the source succeeds with || exit).

♻️ Proposed reorder
 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit
+set -euo pipefail
 source "${SCRIPT_DIR}/shared-constants.sh"
-
-set -euo pipefail
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/generate-skills.sh around lines 25 - 28, Move the
strict-mode invocation so errors in the sourced file are caught: place the set
-euo pipefail line before sourcing shared-constants.sh (or alternatively add an
explicit || exit after the source), ensuring SCRIPT_DIR is still computed
correctly and that the shared-constants.sh inclusion is guarded; update the
script so the sequence is set -euo pipefail, compute SCRIPT_DIR, then source
"${SCRIPT_DIR}/shared-constants.sh" (or source ... || exit) to guarantee
failures in shared-constants.sh are detected.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.agents/scripts/generate-skills.sh:
- Around line 207-227: Pattern 3 currently skips generation if the target
directory exists, which prevents SKILL.md from being recreated after --clean;
update the guard in the Pattern 3 generation loop to check for the SKILL.md file
instead of the directory (replace the if [[ -d "$target_dir" ]]; then continue;
fi with if [[ -f "$target_dir/SKILL.md" ]]; then continue; fi) so mkdir -p
"$target_dir" remains idempotent and --clean + re-run will regenerate the
SKILL.md stubs.
- Around line 159-170: The emitted YAML frontmatter in generate_folder_skill and
generate_leaf_skill uses an unquoted ${description} (see the echo "description:
${description}" lines) which breaks when descriptions contain colons; modify
both functions to emit a properly quoted and escaped description value instead
of raw text: take the description variable (which the awk frontmatter parser on
line 91 strips quotes from), escape embedded double quotes and backslashes, and
output it as a quoted YAML scalar (e.g., description: "escaped description") so
colons and other special characters are safe; update both generate_folder_skill
and generate_leaf_skill to perform this escaping before echoing the description.

---

Outside diff comments:
In @.agents/scripts/generate-skills.sh:
- Around line 240-241: The summary prints "Skipped: $skipped" but skipped is
never incremented; update the script so each place that currently uses continue
to skip an item (the checks for existing "SKILL.md", the special-directory
exclusion, and the top-level file exclusion) also increments the skipped counter
(use "((skipped++))" immediately before each continue), and leave the final
log_info "  Skipped: $skipped (already exist or excluded)" as-is; alternatively,
if you prefer not to track skips, remove that log line — but the preferred fix
is to increment the "skipped" variable at each continue site.

In @.agents/services/hosting/local-hosting.md:
- Line 22: The Quick Reference legacy CLI list is missing the two new commands;
update the bracketed CLI string that currently reads `localhost-helper.sh
[check-port|find-port|list-ports|kill-port|generate-cert|setup-dns|setup-proxy|create-app|start-mcp]`
to include `test-mcp` and `mcp-query` (so it matches the CLI Reference block
where `test-mcp` and `mcp-query` were added); locate the legacy CLI entry in
local-hosting.md and append the new command names to the bracketed list.

---

Nitpick comments:
In @.agents/scripts/generate-skills.sh:
- Around line 25-28: Move the strict-mode invocation so errors in the sourced
file are caught: place the set -euo pipefail line before sourcing
shared-constants.sh (or alternatively add an explicit || exit after the source),
ensuring SCRIPT_DIR is still computed correctly and that the shared-constants.sh
inclusion is guarded; update the script so the sequence is set -euo pipefail,
compute SCRIPT_DIR, then source "${SCRIPT_DIR}/shared-constants.sh" (or source
... || exit) to guarantee failures in shared-constants.sh are detected.

Comment on lines +159 to +170
# Generate pure pointer SKILL.md — no inlined subskill lists
local title
title=$(capitalize "$folder_name")

echo "---"
echo "name: ${skill_name}"
echo "description: ${description}"
echo "---"
echo ""
echo "# ${title}"
echo ""
echo "See [${folder_name}.md](../${folder_name}.md) for full instructions."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n .agents/scripts/generate-skills.sh | head -200

Repository: marcusquinn/aidevops

Length of output: 6270


Unquoted description in YAML frontmatter output produces invalid YAML for descriptions containing colons.

Both generate_folder_skill (line 165) and generate_leaf_skill (line 194) emit unquoted descriptions:

echo "description: ${description}"

The awk function (line 91) strips surrounding quotes from source frontmatter, but the output does not re-add them. YAML plain scalars cannot contain a colon followed by a space, so a description like Redirect: see local-hosting.md for all local development hosting produces invalid YAML:

description: Redirect: see local-hosting.md for all local development hosting

This breaks SKILL.md parsing and agent skill discovery. Re-add and properly escape quotes:

Fix for both functions
-	echo "description: ${description}"
+	# Escape any embedded double-quotes before wrapping
+	local safe_desc="${description//\"/\\\"}"
+	echo "description: \"${safe_desc}\""
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/generate-skills.sh around lines 159 - 170, The emitted YAML
frontmatter in generate_folder_skill and generate_leaf_skill uses an unquoted
${description} (see the echo "description: ${description}" lines) which breaks
when descriptions contain colons; modify both functions to emit a properly
quoted and escaped description value instead of raw text: take the description
variable (which the awk frontmatter parser on line 91 strips quotes from),
escape embedded double quotes and backslashes, and output it as a quoted YAML
scalar (e.g., description: "escaped description") so colons and other special
characters are safe; update both generate_folder_skill and generate_leaf_skill
to perform this escaping before echoing the description.

Comment on lines 207 to 227
if [[ "$CLEAN" == true ]]; then
log_info "Cleaning generated SKILL.md files..."
count=0
while IFS= read -r skill_file; do
if [[ "$DRY_RUN" == true ]]; then
log_warning "Would remove: $skill_file"
else
rm -f "$skill_file"
log_success "Removed: $skill_file"
fi
((count++)) || true
done < <(find "$AGENTS_DIR" -name "SKILL.md" -type f 2>/dev/null)
if [[ $count -eq 0 ]]; then
log_info "No SKILL.md files found to clean"
else
log_info "Cleaned $count SKILL.md files"
fi
exit 0
log_info "Cleaning generated SKILL.md files..."

count=0
while IFS= read -r skill_file; do
if [[ "$DRY_RUN" == true ]]; then
log_warning "Would remove: $skill_file"
else
rm -f "$skill_file"
log_success "Removed: $skill_file"
fi
((count++)) || true
done < <(find "$AGENTS_DIR" -name "SKILL.md" -type f 2>/dev/null)

if [[ $count -eq 0 ]]; then
log_info "No SKILL.md files found to clean"
else
log_info "Cleaned $count SKILL.md files"
fi
exit 0
fi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

--clean + re-run breaks Pattern 3 regeneration — orphaned directories prevent SKILL.md from being recreated.

--clean removes SKILL.md files but leaves behind the directories that Pattern 3 created (e.g., services/hosting/local-hosting/). On the next run, Pattern 3's guard on line 323:

if [[ -d "$target_dir" ]]; then
    continue
fi

sees the directory still exists and skips the file — so those SKILL.md stubs are silently lost after a clean-and-regenerate cycle. Pattern 1 and Pattern 2 are unaffected because they check for SKILL.md file existence, not directory existence.

The minimal fix is to align Pattern 3's guard with Pattern 2's approach:

🐛 Proposed fix
-	# Skip if a matching folder already exists (handled by Pattern 1 or 2)
-	if [[ -d "$target_dir" ]]; then
+	# Skip if SKILL.md already exists (directory may exist from a previous run)
+	if [[ -f "$skill_file" ]]; then
 		continue
 	fi

With this change the mkdir -p "$target_dir" call on line 347 stays idempotent, and --clean + re-run correctly regenerates everything.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/generate-skills.sh around lines 207 - 227, Pattern 3
currently skips generation if the target directory exists, which prevents
SKILL.md from being recreated after --clean; update the guard in the Pattern 3
generation loop to check for the SKILL.md file instead of the directory (replace
the if [[ -d "$target_dir" ]]; then continue; fi with if [[ -f
"$target_dir/SKILL.md" ]]; then continue; fi) so mkdir -p "$target_dir" remains
idempotent and --clean + re-run will regenerate the SKILL.md stubs.

…back

macOS reserves .local for mDNS (Bonjour). Browsers send .local queries to
mDNS multicast before consulting /etc/resolver/local, so dnsmasq alone is
insufficient for browser resolution. Only /etc/hosts reliably overrides mDNS.

Verified empirically: dscacheutil and dig (system resolver) return nothing
for .local domains that exist only in dnsmasq, while dig @127.0.0.1 works.

Changes:
- localdev-helper.sh add: always write /etc/hosts entry (was conditional
  on dnsmasq not being configured)
- localdev-helper.sh init: clarify that dnsmasq is for CLI tools only
- local-hosting.md: rewrite architecture diagram, DNS resolution docs,
  component roles, and troubleshooting to reflect mDNS reality
- local-hosting.md: add note about .test/.localhost TLD alternatives
@github-actions
Copy link

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 40 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Mon Feb 23 00:53:23 UTC 2026: Code review monitoring started
Mon Feb 23 00:53:23 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 40

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 40
  • VULNERABILITIES: 0

Generated on: Mon Feb 23 00:53:26 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.agents/scripts/localdev-helper.sh:
- Around line 839-842: The call to add_hosts_entry "$domain" is marked
“required” but is being silenced by the trailing || true; remove the || true so
failures propagate (or explicitly capture the error and exit non‑zero), ensuring
add_hosts_entry (the function that uses sudo tee to update /etc/hosts) returns a
failing status on permission/IO errors; alternatively, check the return value of
add_hosts_entry and print a clear error and exit if it fails so the script does
not report "localdev add complete" when the browser-resolution step did not
succeed.
- Around line 729-734: The comment and hosts logic are misleading: /etc/hosts
does not support wildcards and cmd_branch never calls add_hosts_entry, so branch
subdomains won't resolve in browsers; fix by updating cmd_branch to call
add_hosts_entry for each created branch subdomain (and update cmd_branch_rm to
call remove_hosts_entry "$subdomain") or else change the comment near the
/etc/hosts section to remove the wildcard claim and clearly state only the apex
domain (handled by cmd_add) is added to /etc/hosts; reference add_hosts_entry,
remove_hosts_entry, cmd_branch, cmd_branch_rm, and cmd_add when making the
change.

In @.agents/services/hosting/local-hosting.md:
- Around line 619-637: The docs show two inaccuracies: the /etc/hosts example
implying wildcard subdomains and claiming the add operation is idempotent;
update the guidance to state that the literal entry "*.myapp.local" does NOT
provide wildcard resolution (clarify only myapp.local resolves) and correct the
remediation for a registered app by explaining that cmd_add (via check_collision
→ is_app_registered) will exit if the app exists, so to re-register you must
remove and re-add (localdev rm myapp && localdev add myapp) or manually fix
/etc/hosts/ports.json rather than re-running localdev-helper.sh add; reference
the literal hosts example, localdev-helper.sh add, cmd_add, check_collision,
is_app_registered and ports.json in the text.
- Around line 85-105: Update the DNS Resolution section to note that while
"localdev add" writes a /etc/hosts entry, "localdev branch" does not write
/etc/hosts entries for branch subdomains (e.g., feature-login.myapp.local), and
because /etc/hosts does not support wildcards the wildcard entry created by
"localdev add" will not make branch subdomains reachable in browsers; state the
user-visible consequences (browsers still use mDNS for .local so branch
subdomains require explicit /etc/hosts entries or a TLD change) and add a short
remediation note (add specific /etc/hosts entries for branch names or use a
non-.local TLD like .test/.localhost) and reference the commands "localdev add"
and "localdev branch" so readers can find the behavior.

Comment on lines +729 to +734
# /etc/hosts Entry (Primary DNS for Browsers)
# =============================================================================

# Add /etc/hosts entry for a domain (fallback when dnsmasq not configured)
# Add /etc/hosts entry for a domain (REQUIRED for .local in browsers)
# macOS reserves .local for mDNS (Bonjour), which intercepts resolution before
# /etc/resolver/local. Only /etc/hosts reliably overrides mDNS for browsers.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

/etc/hosts wildcard entry has no effect — browser access to branch subdomains is unresolved

The new comment block correctly identifies /etc/hosts as the only reliable browser resolution path for .local, but the claim overstates current coverage in two ways:

  1. /etc/hosts has no wildcard support. Line 746 (unchanged) writes *.myapp.local as a literal hostname to /etc/hosts. POSIX /etc/hosts performs exact-string matching only — there is no glob or regex processing. The *.myapp.local entry maps only the literal string *.myapp.local, not any subdomain.

  2. cmd_branch never calls add_hosts_entry. Branch subdomains (e.g., feature-login.myapp.local) are registered in Traefik and ports.json, but receive no /etc/hosts entry. Per the script's own documented model, this means browser access to branch subdomain URLs is silently broken even after a successful localdev branch run.

cmd_add achieves correct browser resolution for the apex domain (myapp.local) only. The broader claim in the comment ("only reliable mechanism") creates a false expectation for branch workflows.

🔧 Suggested remediation

Option A — Add per-subdomain /etc/hosts entries in cmd_branch (recommended):

 	# Step 6: Create Traefik route for branch subdomain
 	create_branch_traefik_route "$app" "$branch" "$port" "$subdomain" || exit 1
+
+	# Step 6a: Add /etc/hosts entry for browser resolution
+	# /etc/hosts has no wildcard support; each subdomain needs an explicit entry.
+	add_hosts_entry "$subdomain" || true

 	# Step 7: Register branch in port registry

Also update cmd_branch_rm to call remove_hosts_entry "$subdomain".

Option B — Adjust the comment to reflect the actual scope:

-# Add /etc/hosts entry for a domain (REQUIRED for .local in browsers)
-# macOS reserves .local for mDNS (Bonjour), which intercepts resolution before
-# /etc/resolver/local. Only /etc/hosts entries reliably override mDNS for .local in browsers.
+# Add /etc/hosts entry for a domain (REQUIRED for .local in browsers).
+# macOS reserves .local for mDNS (Bonjour), which intercepts /etc/resolver/local.
+# Note: /etc/hosts has no wildcard support — each hostname (apex + branch subdomains)
+# requires its own explicit entry. cmd_branch must call this function separately.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/localdev-helper.sh around lines 729 - 734, The comment and
hosts logic are misleading: /etc/hosts does not support wildcards and cmd_branch
never calls add_hosts_entry, so branch subdomains won't resolve in browsers; fix
by updating cmd_branch to call add_hosts_entry for each created branch subdomain
(and update cmd_branch_rm to call remove_hosts_entry "$subdomain") or else
change the comment near the /etc/hosts section to remove the wildcard claim and
clearly state only the apex domain (handled by cmd_add) is added to /etc/hosts;
reference add_hosts_entry, remove_hosts_entry, cmd_branch, cmd_branch_rm, and
cmd_add when making the change.

Comment on lines +839 to +842
# Step 5: Add /etc/hosts entry (required for browser resolution of .local)
# macOS mDNS intercepts .local before /etc/resolver/local, so dnsmasq alone
# is insufficient for browsers. /etc/hosts is the only reliable mechanism.
add_hosts_entry "$domain" || true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

|| true silently swallows a step the comment marks as REQUIRED

The inline comment at lines 839–841 (all newly added) explicitly calls out that the /etc/hosts entry is required for browser resolution. On line 842 the call is guarded with || true, which suppresses any non-zero exit from a sudo tee failure (e.g., permission denied, read-only filesystem). Under set -euo pipefail, this is the only place the REQUIRED step's failure is masked — cmd_add will log "localdev add complete" while the browser-resolution requirement was never satisfied.

🛡️ Proposed fix
-	# Step 5: Add /etc/hosts entry (required for browser resolution of .local)
-	# macOS mDNS intercepts .local before /etc/resolver/local, so dnsmasq alone
-	# is insufficient for browsers. /etc/hosts is the only reliable mechanism.
-	add_hosts_entry "$domain" || true
+	# Step 5: Add /etc/hosts entry (required for browser resolution of .local)
+	# macOS mDNS intercepts .local before /etc/resolver/local, so dnsmasq alone
+	# is insufficient for browsers. /etc/hosts is the only reliable mechanism.
+	if ! add_hosts_entry "$domain"; then
+		print_warning "/etc/hosts entry could not be written — browser resolution of $domain may fail"
+		print_info "  Manually add: sudo bash -c 'echo \"127.0.0.1 $domain\" >> /etc/hosts'"
+	fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/scripts/localdev-helper.sh around lines 839 - 842, The call to
add_hosts_entry "$domain" is marked “required” but is being silenced by the
trailing || true; remove the || true so failures propagate (or explicitly
capture the error and exit non‑zero), ensuring add_hosts_entry (the function
that uses sudo tee to update /etc/hosts) returns a failing status on
permission/IO errors; alternatively, check the return value of add_hosts_entry
and print a clear error and exit if it fails so the script does not report
"localdev add complete" when the browser-resolution step did not succeed.

Comment on lines +85 to +105
### DNS Resolution and the .local mDNS Problem

macOS reserves `.local` for mDNS (Bonjour/multicast DNS). This creates a resolution conflict:

```text
1. /etc/hosts ← LocalWP entries (#Local Site) win here
2. /etc/resolver/local ← dnsmasq wildcard for .local
3. Upstream DNS ← External domains
Browsers (Chrome, Safari, Firefox):
1. /etc/hosts ← WORKS — only reliable method for .local
2. mDNS multicast ← INTERCEPTS .local before resolver files
3. /etc/resolver/local ← NEVER REACHED for .local in browsers

CLI tools (dig, curl, etc.):
1. /etc/hosts ← Checked first
2. /etc/resolver/local ← Works — routes to dnsmasq
3. Upstream DNS ← External domains
```

This order is critical for LocalWP coexistence: domains in `/etc/hosts` always take precedence over dnsmasq.
**Why `localdev add` always writes `/etc/hosts`**: The `/etc/resolver/local` → dnsmasq path only works for CLI tools (`dig`, `curl`). Browsers use the system resolver which sends `.local` queries to mDNS before consulting resolver files. Only `/etc/hosts` entries reliably override mDNS for `.local` domains in browsers.

**dnsmasq is still useful** for wildcard subdomain resolution in CLI tools (e.g., `dig feature-login.myapp.local @127.0.0.1`), but it cannot serve as the primary DNS mechanism for browser access.

> **Future consideration**: `.test` (RFC 6761) and `.localhost` (resolves to `127.0.0.1` natively) avoid the mDNS conflict entirely. Switching TLD would be a breaking change for existing projects but would eliminate the `/etc/hosts` requirement. See [RFC 6761](https://www.rfc-editor.org/rfc/rfc6761) and [RFC 6762 Section 3](https://www.rfc-editor.org/rfc/rfc6762#section-3).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

DNS Resolution section is accurate for apex domains but missing the branch-subdomain caveat

The explanation of the browser/CLI split (lines 90–99) is correct. The caveat at line 101 correctly notes that localdev add always writes an /etc/hosts entry. However, the section does not document that localdev branch does not write /etc/hosts entries for branch subdomains — and that /etc/hosts has no wildcard support, so the *.$domain entry written by add does not cover feature-login.myapp.local in browsers.

📝 Suggested addition after line 103
 **dnsmasq is still useful** for wildcard subdomain resolution in CLI tools (e.g.,
 `dig feature-login.myapp.local `@127.0.0.1``), but it cannot serve as the primary
 DNS mechanism for browser access.
+
+**Branch subdomains in browsers**: `/etc/hosts` has no wildcard support — `*.myapp.local`
+written by `add` is a literal hostname, not a pattern. Each branch subdomain
+(`feature-login.myapp.local`) requires its own `/etc/hosts` entry. Currently `localdev branch`
+does not add these entries automatically; browser access to branch URLs requires manual
+`/etc/hosts` additions or a future enhancement to `cmd_branch`.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/services/hosting/local-hosting.md around lines 85 - 105, Update the
DNS Resolution section to note that while "localdev add" writes a /etc/hosts
entry, "localdev branch" does not write /etc/hosts entries for branch subdomains
(e.g., feature-login.myapp.local), and because /etc/hosts does not support
wildcards the wildcard entry created by "localdev add" will not make branch
subdomains reachable in browsers; state the user-visible consequences (browsers
still use mDNS for .local so branch subdomains require explicit /etc/hosts
entries or a TLD change) and add a short remediation note (add specific
/etc/hosts entries for branch names or use a non-.local TLD like
.test/.localhost) and reference the commands "localdev add" and "localdev
branch" so readers can find the behavior.

Comment on lines +619 to 637
```bash
# Step 1: Check /etc/hosts entry exists (REQUIRED for browsers)
grep 'myapp.local' /etc/hosts
# Should show: 127.0.0.1 myapp.local *.myapp.local # localdev: myapp

# Verify resolver file
cat /etc/resolver/local
# Should contain: nameserver 127.0.0.1
# Step 2: If missing, add it
localdev-helper.sh add myapp # Re-running add is safe (idempotent)

# Check dnsmasq config
grep 'address=/.local/' "$(brew --prefix)/etc/dnsmasq.conf"
# Should contain: address=/.local/127.0.0.1
# Step 3: Flush macOS DNS cache
sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder

# Restart dnsmasq
sudo brew services restart dnsmasq
# Step 4: Verify resolution via system resolver
dscacheutil -q host -a name myapp.local
# Should show: ip_address: 127.0.0.1

# Flush macOS DNS cache
sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder
# Optional: verify dnsmasq works for CLI tools
dig myapp.local @127.0.0.1
# Should return: 127.0.0.1
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Two inaccuracies in the changed DNS troubleshooting steps

1. Line 622 — *.myapp.local shown in expected /etc/hosts output implies wildcard support

# Should show: 127.0.0.1 myapp.local *.myapp.local # localdev: myapp

This entry is written by the script, but *.myapp.local is stored as a literal hostname — not a wildcard. Showing it in "expected" troubleshooting output risks users concluding that branch subdomains are covered via this entry when they are not.

2. Line 625 — add is not idempotent when the app is already registered

localdev-helper.sh add myapp  # Re-running add is safe (idempotent)

cmd_add calls check_collision → is_app_registered, which exits 1 if the app name already exists in ports.json. Re-running add on a registered app will print an error and abort — the /etc/hosts entry will not be repaired. The correct remediation is localdev rm myapp && localdev add myapp, or manually adding the hosts entry.

📝 Suggested corrections
 # Step 1: Check /etc/hosts entry exists (REQUIRED for browsers)
 grep 'myapp.local' /etc/hosts
-# Should show: 127.0.0.1 myapp.local *.myapp.local # localdev: myapp
+# Should show: 127.0.0.1 myapp.local *.myapp.local # localdev: myapp.local
+# Note: *.myapp.local is a literal entry, not a wildcard — branch subdomains need separate entries.

 # Step 2: If missing, add it
-localdev-helper.sh add myapp  # Re-running add is safe (idempotent)
+# NOTE: add will fail if the app is already registered (collision detection).
+# Option A: manually add the hosts entry
+sudo bash -c 'echo "127.0.0.1 myapp.local" >> /etc/hosts'
+# Option B: remove and re-add the entire app (destructive — removes cert/route)
+# localdev-helper.sh rm myapp && localdev-helper.sh add myapp
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.agents/services/hosting/local-hosting.md around lines 619 - 637, The docs
show two inaccuracies: the /etc/hosts example implying wildcard subdomains and
claiming the add operation is idempotent; update the guidance to state that the
literal entry "*.myapp.local" does NOT provide wildcard resolution (clarify only
myapp.local resolves) and correct the remediation for a registered app by
explaining that cmd_add (via check_collision → is_app_registered) will exit if
the app exists, so to re-register you must remove and re-add (localdev rm myapp
&& localdev add myapp) or manually fix /etc/hosts/ports.json rather than
re-running localdev-helper.sh add; reference the literal hosts example,
localdev-helper.sh add, cmd_add, check_collision, is_app_registered and
ports.json in the text.

@marcusquinn marcusquinn merged commit 61e447d into main Feb 23, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant