Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .bash_aliases.d/ai-providers.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
DOT_DEN="${DOT_DEN:-$HOME/ppv/pillars/dotfiles}"

alias claude='claude --mcp-config "$DOT_DEN/mcp/mcp.json" --add-dir "$DOT_DEN/knowledge"'
alias q='q --mcp-config "$DOT_DEN/mcp/mcp.json" --add-dir "$DOT_DEN/knowledge"'

# Amazon Q trusted tools (mirrors Claude's .claude/settings.json trusted tools)
TRUSTED_TOOLS="mcp__git__git_status,mcp__git__git_diff,mcp__git__git_diff_staged,mcp__git__git_diff_unstaged,mcp__git__git_log,mcp__git__git_show,mcp__git__git_fetch,mcp__git__git_branch,mcp__git__git_blame,mcp__git__git_describe,mcp__git__git_shortlog,mcp__git__git_reflog,mcp__git__git_worktree_list,mcp__git__git_remote,mcp__git__git_add,mcp__git__git_commit,mcp__git__git_checkout,mcp__git__git_create_branch,mcp__git__git_stash,mcp__git__git_stash_pop,mcp__github-read,mcp__brave-search,mcp__filesystem,mcp__awslabs.aws-documentation-mcp-server,mcp__gdrive"

# Add work-specific tools if on work machine
if [ "${WORK_MACHINE:-false}" = "true" ]; then
TRUSTED_TOOLS="$TRUSTED_TOOLS,mcp__atlassian,mcp__gitlab"
fi

alias q='q chat --trust-tools="$TRUSTED_TOOLS" --mcp-config "$DOT_DEN/mcp/mcp.json" --add-dir "$DOT_DEN/knowledge"'
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,15 @@ The dotfiles include pre-configured MCP servers for:

Work-specific servers (Atlassian, GitLab) require `WORK_MACHINE=true` in `~/.bash_exports.local`.

### Claude Model Preferences

Personal machines automatically use the Opus model (claude-opus-4-20250514) for maximum capability. This is controlled by the `WORK_MACHINE` environment variable:

- **Personal machines**: Set `WORK_MACHINE="false"` in `~/.bash_exports.local` → Opus model by default
- **Work machines**: Set `WORK_MACHINE="true"` → Standard model selection

No manual model switching required - the correct model is automatically selected based on your machine type.

## Secret Management

Sensitive information like API tokens are stored in `~/.bash_secrets` (not tracked in git).
Expand Down
5 changes: 4 additions & 1 deletion knowledge/procedures/mcp-prompts.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# MCP Prompts

To add prompts to Amazon Q CLI, add them to your MCP servers.
**Amazon Q CLI:** `'@close-issue 934'` (single quotes required)
**Claude Code:** `/close-issue 934` (slash commands, better autocomplete)

Both use the same MCP servers from `mcp/mcp.json` - just different syntax.

→ [MCP Prompts PoC](~/ppv/pillars/dotfiles/mcp/prompts/README.md)

Expand Down
85 changes: 84 additions & 1 deletion mcp/servers/git-mcp-server/src/mcp_server_git/server.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import logging
import os
import re
from enum import Enum
from pathlib import Path
from typing import Sequence
Expand Down Expand Up @@ -1836,6 +1837,17 @@ async def list_prompts() -> list[Prompt]:
required=False
)
]
),
Prompt(
name="close-issue",
description="Complete and implement a GitHub issue with git workflow",
arguments=[
PromptArgument(
name="issue_number",
description="GitHub issue number to close",
required=True
)
]
)
]

Expand Down Expand Up @@ -2021,6 +2033,77 @@ async def get_prompt(name: str, arguments: dict | None = None) -> GetPromptResul
]
)

elif name == "close-issue":
# Extract issue number from arguments
issue_number = arguments.get("issue_number") if arguments else None

if not issue_number:
return GetPromptResult(
description="Error: issue_number is required",
messages=[
PromptMessage(
role="user",
content=TextContent(
type="text",
text="Error: issue_number argument is required for close-issue prompt"
)
)
]
)

# Read the close-issue template
try:
# Try to get dotfiles path from environment or use relative path
dot_den = os.getenv("DOT_DEN")
if dot_den:
dotfiles_path = Path(dot_den)
else:
# Try to find dotfiles relative to current working directory
cwd = Path.cwd()
if "dotfiles" in str(cwd):
# Find the dotfiles root
dotfiles_path = cwd
while dotfiles_path.name != "dotfiles" and dotfiles_path.parent != dotfiles_path:
dotfiles_path = dotfiles_path.parent
else:
# Fallback to home directory location
dotfiles_path = Path.home() / "ppv" / "pillars" / "dotfiles"

template_path = dotfiles_path / "commands" / "templates" / "close-issue.md"
with open(template_path, 'r') as f:
template_content = f.read()

# Replace the placeholder with the actual issue number
prompt_text = template_content.replace("{{ ISSUE_NUMBER }}", str(issue_number))

# Process INJECT directives
inject_pattern = r'\{\{ INJECT:([^}]+) \}\}'

def process_inject(match):
inject_path = match.group(1)
knowledge_base = dotfiles_path / "knowledge"
full_path = knowledge_base / inject_path
try:
with open(full_path, 'r') as f:
return f.read()
except Exception:
return f"[Unable to inject {inject_path}]"

prompt_text = re.sub(inject_pattern, process_inject, prompt_text)

except Exception as e:
prompt_text = f"Error reading close-issue template: {str(e)}"

return GetPromptResult(
description=f"Complete and implement GitHub issue #{issue_number}",
messages=[
PromptMessage(
role="user",
content=TextContent(type="text", text=prompt_text)
)
]
)

else:
return GetPromptResult(
description=f"Unknown prompt: {name}",
Expand All @@ -2029,7 +2112,7 @@ async def get_prompt(name: str, arguments: dict | None = None) -> GetPromptResul
role="user",
content=TextContent(
type="text",
text=f"Unknown prompt: {name}. Available prompts: commit-message, pr-description"
text=f"Unknown prompt: {name}. Available prompts: commit-message, pr-description, close-issue"
)
)
]
Expand Down