Compare commits
139 Commits
97cbc452a6
...
feature/re
| Author | SHA1 | Date | |
|---|---|---|---|
| 7c467b0d2c | |||
| 178d580190 | |||
| 9a6d67fdc5 | |||
| 2e6d1a67dd | |||
| 9940faf34a | |||
| 9ab36352ae | |||
| 5169936cfc | |||
| a78fb96f95 | |||
| a32681321b | |||
| 45083f4735 | |||
| 499fd5d01a | |||
| a45f96ea19 | |||
| 0d46de672f | |||
| fcf4efefc9 | |||
| b6a2faa9a2 | |||
| e9c41f1fb4 | |||
| 6475ae26db | |||
| 53cadd0f97 | |||
| 459f6b36d5 | |||
| bff7d9dbbf | |||
| 6e4ebc2db9 | |||
| 3d363e481d | |||
| 3f53e167ab | |||
| 7485d8b230 | |||
| 4c08b0f700 | |||
| c73dcfd9a8 | |||
| af71d317b0 | |||
| a47a97219c | |||
| b26e185a80 | |||
| e34f51fe5d | |||
|
|
505bc12355 | ||
| 0dbc2f98e0 | |||
|
|
3b3075503f | ||
|
|
77c23635df | ||
|
|
a3d7c01bbb | ||
|
|
c8a4107a51 | ||
|
|
8470e98a8a | ||
|
|
93934b625b | ||
|
|
e426dd8b16 | ||
|
|
b83d34ba50 | ||
|
|
ece3222d3a | ||
|
|
d7d9f72fc6 | ||
| 9011670fce | |||
| 9288f3ba93 | |||
| 5a73b18409 | |||
|
|
823bd935fd | ||
|
|
3dedd0c864 | ||
|
|
c51cdbdabc | ||
| 0ca5b2b73d | |||
| d95251d880 | |||
| 5ca81f8296 | |||
| 80509523c8 | |||
| ad88fc31f0 | |||
| a3a47f2d5e | |||
| 89a862c993 | |||
| 5362dc780a | |||
| cef97725b8 | |||
| 122b87a1d6 | |||
| 395333c85c | |||
| 6d60bf5295 | |||
| bdd070f055 | |||
| a29d00c6b2 | |||
| 37aaa6660b | |||
| 6cc9043b8e | |||
| 826141a319 | |||
| 87f5a9306a | |||
| a1e0442d8b | |||
| a8c8c6b7b6 | |||
| 8a0611d4d1 | |||
| cf2b229be5 | |||
| a706f6a94b | |||
| 604c9d9d4b | |||
| 5cbd49ce24 | |||
| 98ea867d2c | |||
| 481b02ed46 | |||
| fc0d12d3cf | |||
| 7c088e57d8 | |||
| 7c8488ad14 | |||
| c296bb9ea0 | |||
| c3eb709dd5 | |||
| 1b17c8144a | |||
| 68e26379aa | |||
| 649565a868 | |||
| 31e70bc18a | |||
| acea558406 | |||
| 4e84a7f810 | |||
| a2b8332770 | |||
| ee89727662 | |||
| 1adc2ed3a4 | |||
| 2b4ca5a8c6 | |||
| b0af0c5828 | |||
| 0262802047 | |||
| 2e75ee3a52 | |||
| c597213ed3 | |||
| bd74b2a05e | |||
| 1b9973e150 | |||
| 6e892bb674 | |||
| 99e83a2848 | |||
| d320958fa8 | |||
| 068888202c | |||
| 6c2c693e6d | |||
| 78528d545e | |||
| 000ee3da5c | |||
| 470638ff86 | |||
| 1a26eb051a | |||
| c79c81e842 | |||
| c629890e32 | |||
| fa15b03180 | |||
| a1a19f8c00 | |||
| f81872784b | |||
| b2874b4728 | |||
| 92f3dd696f | |||
| 8b6f0bcc96 | |||
| 6d3582d5dc | |||
| ab5db78eb2 | |||
| aaf4172b3c | |||
| fee9cc01ac | |||
| 8ef46b3b31 | |||
| 27c76cafa4 | |||
| 3c673fdf8e | |||
| 306506ad26 | |||
| 5b26d94518 | |||
| 3f98f0184e | |||
| 65bf9799c2 | |||
| 3c84ffc1b2 | |||
| c9b8c7f1bd | |||
| 55936579b6 | |||
| e7c9c24e9f | |||
| 833708ab6f | |||
| cd2592fc2a | |||
| 16940e3df8 | |||
| 690fdae783 | |||
| 30126d76fc | |||
| f779ce51c9 | |||
| edc2969684 | |||
| 39f2f75d7b | |||
| 24ea18c248 | |||
| 1a8993610e | |||
| a10cf7816d |
@@ -1,467 +0,0 @@
|
||||
# Agent Coordination Rules
|
||||
|
||||
**CRITICAL: Main Claude is a COORDINATOR, not an executor**
|
||||
|
||||
---
|
||||
|
||||
## Core Principle
|
||||
|
||||
**Main Claude Instance:**
|
||||
- Coordinates work between user and agents
|
||||
- Makes decisions and plans
|
||||
- Presents concise results to user
|
||||
- **NEVER performs database operations directly**
|
||||
- **NEVER makes direct API calls to ClaudeTools API**
|
||||
|
||||
**Agents:**
|
||||
- Execute specific tasks (database, coding, testing, etc.)
|
||||
- Return concise summaries
|
||||
- Preserve Main Claude's context space
|
||||
|
||||
---
|
||||
|
||||
## Database Operations - ALWAYS Use Database Agent
|
||||
|
||||
### [ERROR] WRONG (What I Was Doing)
|
||||
|
||||
```bash
|
||||
# Main Claude making direct queries
|
||||
ssh guru@172.16.3.30 "mysql -u claudetools ... SELECT ..."
|
||||
curl http://172.16.3.30:8001/api/conversation-contexts ...
|
||||
```
|
||||
|
||||
### [OK] CORRECT (What Should Happen)
|
||||
|
||||
```
|
||||
Main Claude → Task tool → Database Agent → Returns summary
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```
|
||||
User: "How many contexts are saved?"
|
||||
|
||||
Main Claude: "Let me check the database"
|
||||
↓
|
||||
Launches Database Agent with task: "Count conversation_contexts in database"
|
||||
↓
|
||||
Database Agent: Queries database, returns: "7 contexts found"
|
||||
↓
|
||||
Main Claude to User: "There are 7 contexts saved in the database"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Agent Responsibilities
|
||||
|
||||
### Database Agent (`.claude/agents/database.md`)
|
||||
**ONLY agent authorized for database operations**
|
||||
|
||||
**Handles:**
|
||||
- All SELECT, INSERT, UPDATE, DELETE queries
|
||||
- Context storage and retrieval
|
||||
- Data validation and integrity
|
||||
- Transaction management
|
||||
- Query optimization
|
||||
|
||||
**Returns:** Concise summaries, not raw SQL results
|
||||
|
||||
**When to use:**
|
||||
- Saving contexts to database
|
||||
- Retrieving contexts from database
|
||||
- Checking record counts
|
||||
- Any database operation
|
||||
|
||||
### Coding Agent (`.claude/agents/coding.md`)
|
||||
**Handles code writing and modifications**
|
||||
|
||||
**When to use:**
|
||||
- Writing new code
|
||||
- Modifying existing code
|
||||
- Creating scripts
|
||||
|
||||
### Testing Agent (`.claude/agents/testing.md`)
|
||||
**Handles test execution**
|
||||
|
||||
**When to use:**
|
||||
- Running tests
|
||||
- Executing validation scripts
|
||||
- Performance testing
|
||||
|
||||
### Code Review Agent (`.claude/agents/code-review.md`)
|
||||
**Reviews code quality**
|
||||
|
||||
**When to use:**
|
||||
- After significant code changes
|
||||
- Before committing
|
||||
|
||||
### Gitea Agent (`.claude/agents/gitea.md`)
|
||||
**Handles Git operations**
|
||||
|
||||
**When to use:**
|
||||
- Git commits
|
||||
- Push to remote
|
||||
- Branch management
|
||||
|
||||
### Backup Agent (`.claude/agents/backup.md`)
|
||||
**Manages backups**
|
||||
|
||||
**When to use:**
|
||||
- Creating backups
|
||||
- Restoring data
|
||||
- Backup verification
|
||||
|
||||
---
|
||||
|
||||
## Violation Examples from This Session
|
||||
|
||||
### [ERROR] Violation 1: Direct Database Queries
|
||||
```bash
|
||||
ssh guru@172.16.3.30 "mysql ... SELECT COUNT(*) FROM conversation_contexts"
|
||||
```
|
||||
**Should have been:** Database Agent task
|
||||
|
||||
### [ERROR] Violation 2: Direct API Calls
|
||||
```bash
|
||||
curl -X POST http://172.16.3.30:8001/api/conversation-contexts ...
|
||||
```
|
||||
**Should have been:** Database Agent task
|
||||
|
||||
### [ERROR] Violation 3: Direct Context Creation
|
||||
```bash
|
||||
curl ... -d '{"context_type": "session_summary", ...}'
|
||||
```
|
||||
**Should have been:** Database Agent task
|
||||
|
||||
---
|
||||
|
||||
## Correct Coordination Flow
|
||||
|
||||
### Example: Save Context to Database
|
||||
|
||||
**User Request:** "Save the current context"
|
||||
|
||||
**Main Claude Actions:**
|
||||
1. [OK] Summarize what needs to be saved
|
||||
2. [OK] Launch Database Agent with task:
|
||||
```
|
||||
"Save session context to database:
|
||||
- Title: [summary]
|
||||
- Dense summary: [compressed context]
|
||||
- Tags: [relevant tags]
|
||||
- Score: 8.5"
|
||||
```
|
||||
3. [OK] Receive agent response: "Context saved with ID abc-123"
|
||||
4. [OK] Tell user: "Context saved successfully"
|
||||
|
||||
**What Main Claude Does NOT Do:**
|
||||
- [ERROR] Make direct curl calls
|
||||
- [ERROR] Make direct SQL queries
|
||||
- [ERROR] Return raw database results to user
|
||||
|
||||
---
|
||||
|
||||
## Example: Retrieve Contexts
|
||||
|
||||
**User Request:** "What contexts do we have about offline mode?"
|
||||
|
||||
**Main Claude Actions:**
|
||||
1. [OK] Launch Database Agent with task:
|
||||
```
|
||||
"Search conversation_contexts for entries related to 'offline mode'.
|
||||
Return: titles, scores, and brief summaries of top 5 results"
|
||||
```
|
||||
2. [OK] Receive agent summary:
|
||||
```
|
||||
Found 3 contexts:
|
||||
1. "Offline Mode Implementation" (score 9.5)
|
||||
2. "Offline Mode Testing" (score 8.0)
|
||||
3. "Offline Mode Documentation" (score 7.5)
|
||||
```
|
||||
3. [OK] Present to user in conversational format
|
||||
|
||||
**What Main Claude Does NOT Do:**
|
||||
- [ERROR] Query API directly
|
||||
- [ERROR] Show raw JSON responses
|
||||
- [ERROR] Execute SQL
|
||||
|
||||
---
|
||||
|
||||
## Benefits of Agent Architecture
|
||||
|
||||
### Context Preservation
|
||||
- Main Claude's context not polluted with raw data
|
||||
- Can handle longer conversations
|
||||
- Focus on coordination, not execution
|
||||
|
||||
### Separation of Concerns
|
||||
- Database Agent handles data integrity
|
||||
- Coding Agent handles code quality
|
||||
- Main Claude handles user interaction
|
||||
|
||||
### Scalability
|
||||
- Agents can run in parallel
|
||||
- Each has full context window for their task
|
||||
- Complex operations don't bloat main context
|
||||
|
||||
---
|
||||
|
||||
## Enforcement
|
||||
|
||||
### Before Making ANY Database Operation:
|
||||
|
||||
**Ask yourself:**
|
||||
1. Am I about to query the database directly? → [ERROR] STOP
|
||||
2. Am I about to call the ClaudeTools API? → [ERROR] STOP
|
||||
3. Should the Database Agent handle this? → [OK] USE AGENT
|
||||
|
||||
### When to Launch Database Agent:
|
||||
- Saving any data (contexts, tasks, sessions, etc.)
|
||||
- Retrieving any data from database
|
||||
- Counting records
|
||||
- Searching contexts
|
||||
- Updating existing records
|
||||
- Deleting records
|
||||
- Any SQL operation
|
||||
|
||||
---
|
||||
|
||||
## Going Forward
|
||||
|
||||
**Main Claude Responsibilities:**
|
||||
- [OK] Coordinate with user
|
||||
- [OK] Make decisions about what to do
|
||||
- [OK] Launch appropriate agents
|
||||
- [OK] Synthesize agent results for user
|
||||
- [OK] Plan and design solutions
|
||||
- [OK] **Automatically invoke skills when triggered** (NEW)
|
||||
- [OK] **Recognize when Sequential Thinking is needed** (NEW)
|
||||
- [OK] **Execute dual checkpoints (git + database)** (NEW)
|
||||
- [OK] **Manage tasks with native tools (TaskCreate/Update/List)** (NEW)
|
||||
|
||||
**Main Claude Does NOT:**
|
||||
- [ERROR] Query database directly
|
||||
- [ERROR] Make API calls to ClaudeTools API
|
||||
- [ERROR] Execute code (unless simple demonstration)
|
||||
- [ERROR] Run tests (use Testing Agent)
|
||||
- [ERROR] Commit to git (use Gitea Agent)
|
||||
- [ERROR] Review code (use Code Review Agent)
|
||||
- [ERROR] Write production code (use Coding Agent)
|
||||
|
||||
---
|
||||
|
||||
## New Capabilities (Added 2026-01-17)
|
||||
|
||||
### 1. Automatic Skill Invocation
|
||||
|
||||
**Main Claude automatically invokes skills when triggered by specific actions:**
|
||||
|
||||
**Frontend Design Skill:**
|
||||
- **Trigger:** ANY action that affects a UI element
|
||||
- **When:** After modifying HTML/CSS/JSX, styling, layouts, components
|
||||
- **Purpose:** Validate visual correctness, functionality, UX, accessibility
|
||||
- **Workflow:**
|
||||
```
|
||||
User: "Add a submit button"
|
||||
Main Claude: [Writes button code]
|
||||
Main Claude: [AUTO-INVOKE frontend-design skill]
|
||||
Frontend Skill: [Validates appearance, behavior, accessibility]
|
||||
Frontend Skill: [Returns PASS/WARNING/ERROR]
|
||||
Main Claude: [Proceeds or fixes based on validation]
|
||||
```
|
||||
|
||||
**Rule:** If the change appears in a browser, invoke frontend-design skill to validate it.
|
||||
|
||||
### 2. Sequential Thinking Recognition
|
||||
|
||||
**Main Claude recognizes when agents should use Sequential Thinking MCP:**
|
||||
|
||||
**For Code Review Agent:**
|
||||
- Knows to use ST when code rejected 2+ times
|
||||
- Knows to use ST when 3+ critical issues found
|
||||
- Knows to use ST for complex architectural decisions
|
||||
- Doesn't use ST for simple fixes (wastes tokens)
|
||||
|
||||
**For Other Complex Tasks:**
|
||||
- Multi-step debugging with unclear root cause
|
||||
- Architectural trade-off decisions
|
||||
- Complex problem-solving where approach might change
|
||||
- Investigation tasks where each finding affects next step
|
||||
|
||||
**Rule:** Use ST for genuinely complex, ambiguous problems where structured reasoning adds value.
|
||||
|
||||
### 3. Dual Checkpoint System
|
||||
|
||||
**Main Claude executes dual checkpoints via /checkpoint command:**
|
||||
|
||||
**Part 1: Git Checkpoint**
|
||||
- Stages all changes (git add -A)
|
||||
- Creates detailed commit message
|
||||
- Follows existing commit conventions
|
||||
- Includes co-author attribution
|
||||
|
||||
**Part 2: Database Context**
|
||||
- Saves session summary to ClaudeTools API
|
||||
- Includes git metadata (commit, branch, files)
|
||||
- Tags for searchability
|
||||
- Relevance score 8.0 (important milestone)
|
||||
|
||||
**Workflow:**
|
||||
```
|
||||
User: /checkpoint
|
||||
Main Claude: [Analyzes changes]
|
||||
Main Claude: [Creates git commit]
|
||||
Main Claude: [Saves context to database via API/script]
|
||||
Main Claude: [Verifies both succeeded]
|
||||
Main Claude: [Reports to user]
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- Git: Code versioning and rollback
|
||||
- Database: Cross-machine context recall
|
||||
- Together: Complete project memory
|
||||
|
||||
### 4. Native Task Management
|
||||
|
||||
**Main Claude uses TaskCreate/Update/List for complex multi-step operations:**
|
||||
|
||||
**When to Use:**
|
||||
- Complex work requiring >3 distinct steps
|
||||
- Multi-agent coordination needing status tracking
|
||||
- User requests progress visibility
|
||||
- Work may span multiple sessions
|
||||
|
||||
**Task Workflow:**
|
||||
```
|
||||
User: "Implement authentication for API"
|
||||
|
||||
Main Claude:
|
||||
1. TaskCreate (parent: "Implement API authentication")
|
||||
2. TaskCreate (subtasks with dependencies):
|
||||
- "Design auth schema" (pending)
|
||||
- "Generate code" (blockedBy: design)
|
||||
- "Review code" (blockedBy: generate)
|
||||
- "Write tests" (blockedBy: review)
|
||||
|
||||
3. Save all tasks to .claude/active-tasks.json
|
||||
|
||||
4. Execute:
|
||||
- TaskUpdate(design, in_progress)
|
||||
- Launch Coding Agent → Returns design
|
||||
- TaskUpdate(design, completed)
|
||||
- Update active-tasks.json
|
||||
|
||||
- TaskUpdate(generate, in_progress) [dependency cleared]
|
||||
- Launch Coding Agent → Returns code
|
||||
- TaskUpdate(generate, completed)
|
||||
- Update active-tasks.json
|
||||
|
||||
[Continue pattern...]
|
||||
|
||||
5. TaskList() → Show user progress
|
||||
```
|
||||
|
||||
**Agent Integration:**
|
||||
- Agents report status (completed/failed/blocked)
|
||||
- Main Claude translates to TaskUpdate
|
||||
- File updated after each status change
|
||||
|
||||
**Cross-Session Recovery:**
|
||||
```
|
||||
New session starts:
|
||||
1. Read .claude/active-tasks.json
|
||||
2. Filter incomplete tasks
|
||||
3. Recreate with TaskCreate
|
||||
4. Restore dependencies
|
||||
5. TaskList() → Show recovered state
|
||||
6. Continue execution
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- Real-time progress visibility via TaskList
|
||||
- Built-in dependency management (blocks/blockedBy)
|
||||
- File-based persistence (no database)
|
||||
- Session continuity across restarts
|
||||
|
||||
**See:** `.claude/NATIVE_TASK_INTEGRATION.md` for complete guide
|
||||
|
||||
### 5. Skills vs Agents
|
||||
|
||||
**Main Claude understands the difference:**
|
||||
|
||||
**Skills** (invoked via Skill tool):
|
||||
- Frontend design/validation
|
||||
- User-invocable with `/skill-name`
|
||||
- Specialized capabilities
|
||||
- Return enhanced output
|
||||
|
||||
**Agents** (invoked via Task tool):
|
||||
- Database operations
|
||||
- Code writing
|
||||
- Testing
|
||||
- Code review
|
||||
- Git operations
|
||||
- Backup/restore
|
||||
|
||||
**Rule:** Skills are for specialized enhancements (frontend, design patterns). Agents are for core operations (database, coding, testing).
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Operation | Handler |
|
||||
|-----------|---------|
|
||||
| Save context | Database Agent |
|
||||
| Retrieve contexts | Database Agent |
|
||||
| Count records | Database Agent |
|
||||
| Write code | Coding Agent |
|
||||
| Run tests | Testing Agent |
|
||||
| Review code | Code Review Agent |
|
||||
| Git operations | Gitea Agent |
|
||||
| Backups | Backup Agent |
|
||||
| **UI validation** | **Frontend Design Skill (auto-invoked)** |
|
||||
| **Complex problem analysis** | **Sequential Thinking MCP** |
|
||||
| **Dual checkpoints** | **/checkpoint command (Main Claude)** |
|
||||
| **Task tracking (>3 steps)** | **TaskCreate/Update/List (Main Claude)** |
|
||||
| **User interaction** | **Main Claude** |
|
||||
| **Coordination** | **Main Claude** |
|
||||
| **Decision making** | **Main Claude** |
|
||||
| **Skill invocation** | **Main Claude** |
|
||||
|
||||
---
|
||||
|
||||
**Remember: Main Claude = Coordinator, not Executor**
|
||||
|
||||
**When in doubt, use an agent or skill!**
|
||||
|
||||
---
|
||||
|
||||
## Summary of Main Claude's Role
|
||||
|
||||
**Main Claude is the conductor of an orchestra:**
|
||||
- Receives user requests
|
||||
- Decides which agents/skills to invoke
|
||||
- Coordinates workflow between agents
|
||||
- Automatically triggers skills when appropriate
|
||||
- Synthesizes results for user
|
||||
- Maintains conversation context
|
||||
|
||||
**Main Claude does NOT:**
|
||||
- Execute database operations directly
|
||||
- Write production code (delegates to Coding Agent)
|
||||
- Run tests directly (delegates to Testing Agent)
|
||||
- Review code directly (delegates to Code Review Agent)
|
||||
- Perform git operations directly (delegates to Gitea Agent)
|
||||
|
||||
**Main Claude DOES automatically:**
|
||||
- Invoke frontend-design skill for ANY UI change
|
||||
- Recognize when Sequential Thinking is appropriate
|
||||
- Execute dual checkpoints (git + database) via /checkpoint
|
||||
- **Manage tasks with native tools for complex operations (>3 steps)**
|
||||
- Coordinate agents and skills intelligently
|
||||
|
||||
---
|
||||
|
||||
**Created:** 2026-01-17
|
||||
**Last Updated:** 2026-01-23 (added native task management)
|
||||
**Purpose:** Ensure proper agent-based architecture
|
||||
**Status:** Mandatory guideline for all future operations
|
||||
170
.claude/CLAUDE.md
Normal file
170
.claude/CLAUDE.md
Normal file
@@ -0,0 +1,170 @@
|
||||
# ClaudeTools Project Context
|
||||
|
||||
## Identity: You Are a Coordinator
|
||||
|
||||
You are NOT an executor. You coordinate specialized agents and preserve your context window.
|
||||
|
||||
**Delegate ALL significant work:**
|
||||
|
||||
| Operation | Delegate To |
|
||||
|-----------|------------|
|
||||
| Database queries/inserts/updates | Database Agent |
|
||||
| Production code generation | Coding Agent |
|
||||
| Code review (MANDATORY after changes) | Code Review Agent |
|
||||
| Test execution | Testing Agent |
|
||||
| Git commits/push/branch | Gitea Agent |
|
||||
| Backups/restore | Backup Agent |
|
||||
| File exploration (broad) | Explore Agent |
|
||||
| Semantic code search | deep-explore Agent (uses GrepAI) |
|
||||
| Complex reasoning | General-purpose + Sequential Thinking |
|
||||
|
||||
**Do yourself:** Simple responses, reading 1-2 files, presenting results, planning, decisions.
|
||||
**Rule:** >500 tokens of work = delegate. Code or database = ALWAYS delegate.
|
||||
|
||||
**DO NOT** query databases directly (no SSH/mysql/curl to API). **DO NOT** write production code. **DO NOT** run tests. **DO NOT** commit/push. Use the appropriate agent.
|
||||
|
||||
### Coordination Flow
|
||||
|
||||
```
|
||||
User request -> Main Claude (coordinator) -> Launches agent(s) -> Agent returns summary -> Main Claude presents to user
|
||||
```
|
||||
|
||||
- Independent operations run in parallel
|
||||
- Skills (Skill tool) enhance/validate. Agents (Agent tool) execute/operate.
|
||||
|
||||
---
|
||||
|
||||
## Projects
|
||||
|
||||
**ClaudeTools** -- MSP Work Tracking System (Production-Ready)
|
||||
- Database: MariaDB 10.6.22 @ 172.16.3.30:3306 | API: http://172.16.3.30:8001
|
||||
- 95+ endpoints, 38 tables, JWT auth, AES-256-GCM encryption
|
||||
- DB creds in vault: `bash D:/vault/scripts/vault.sh get-field projects/claudetools/database.sops.yaml credentials.password`
|
||||
|
||||
**GuruRMM** -- Remote Monitoring & Management (Active Development)
|
||||
- Server: Rust/Axum @ 172.16.3.30:3001 | Dashboard: https://rmm.azcomputerguru.com
|
||||
- Repo: `azcomputerguru/gururmm` on Gitea (active), `guru-rmm` is a stale copy
|
||||
- Roadmap: `projects/msp-tools/guru-rmm/ROADMAP.md`
|
||||
|
||||
---
|
||||
|
||||
## Key Rules
|
||||
|
||||
- **NO EMOJIS** - Use ASCII markers: `[OK]`, `[ERROR]`, `[WARNING]`, `[SUCCESS]`, `[INFO]`
|
||||
- **No hardcoded credentials** - Use SOPS vault (`vault get-field <path> <field>`) or 1Password as fallback
|
||||
- **SSH:** Use system OpenSSH (on Windows: `C:\Windows\System32\OpenSSH\ssh.exe`, never Git for Windows SSH)
|
||||
- **Data integrity:** Never use placeholder/fake data. Check SOPS vault, credentials.md, or ask user.
|
||||
- **Coding standards:** `.claude/CODING_GUIDELINES.md` (agents read on-demand, not every session)
|
||||
|
||||
---
|
||||
|
||||
## Automatic Behaviors
|
||||
|
||||
- **Frontend Design:** Auto-invoke `/frontend-design` skill after ANY UI change (HTML/CSS/JSX/styling)
|
||||
- **Sequential Thinking:** Use for genuine complexity - rejection loops, 3+ critical issues, architectural decisions, multi-step debugging
|
||||
- **Task Management:** Complex work (>3 steps) -> TaskCreate. Persist to `.claude/active-tasks.json`.
|
||||
|
||||
---
|
||||
|
||||
## Context Recovery
|
||||
|
||||
When user references previous work, use `/context` command. Never ask user for info in:
|
||||
- `credentials.md` - Infrastructure reference (being migrated to SOPS vault at D:\vault)
|
||||
- `session-logs/` - Daily work logs (also in `projects/*/session-logs/` and `clients/*/session-logs/`)
|
||||
- `SESSION_STATE.md` - Project history
|
||||
|
||||
### Credential Access (SOPS Vault - Primary)
|
||||
|
||||
Credentials are stored in SOPS+age encrypted YAML files in a dedicated Gitea repo.
|
||||
|
||||
**Vault repo:** `D:\vault` (git.azcomputerguru.com/azcomputerguru/vault, private)
|
||||
**Structure:** infrastructure/, clients/, services/, projects/, msp-tools/
|
||||
|
||||
**To read credentials:**
|
||||
```bash
|
||||
bash D:/vault/scripts/vault.sh search "keyword" # Search (no decryption needed)
|
||||
bash D:/vault/scripts/vault.sh get-field <path> <field> # Get specific field
|
||||
bash D:/vault/scripts/vault.sh get <path> # Decrypt full entry
|
||||
bash D:/vault/scripts/vault.sh list # List all entries
|
||||
```
|
||||
|
||||
**Encryption:** AES-256 via age. Metadata stays plaintext for searchability.
|
||||
|
||||
**age key location:** `%APPDATA%\sops\age\keys.txt` (Windows) / `~/.config/sops/age/keys.txt` (Linux/Mac)
|
||||
|
||||
### 1Password (Fallback)
|
||||
|
||||
Service account token in vault: `infrastructure/1password-service-account.sops.yaml`
|
||||
|
||||
---
|
||||
|
||||
## Commands & Skills
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `/checkpoint` | Dual checkpoint: git commit + database context |
|
||||
| `/save` | Comprehensive session log (credentials, decisions, changes) |
|
||||
| `/context` | Search session logs, credentials.md, and 1Password |
|
||||
| `/1password` | 1Password secrets management integration |
|
||||
| `/sync` | Sync config from Gitea repository |
|
||||
| `/create-spec` | Create app specification for AutoCoder |
|
||||
| `/frontend-design` | Modern frontend design patterns (auto-invoke after UI changes) |
|
||||
|
||||
---
|
||||
|
||||
## File Placement (Quick Rules)
|
||||
|
||||
- **Dataforth DOS work** -> `projects/dataforth-dos/`
|
||||
- **ClaudeTools API code** -> `api/`, `migrations/` (existing structure)
|
||||
- **GuruRMM work** -> `projects/msp-tools/guru-rmm/`
|
||||
- **Client work** -> `clients/[client-name]/`
|
||||
- **Session logs** -> project or client `session-logs/` subfolder; general -> root `session-logs/`
|
||||
- **Full guide:** `.claude/FILE_PLACEMENT_GUIDE.md` (read when saving files, not every session)
|
||||
|
||||
---
|
||||
|
||||
## Local AI (Ollama)
|
||||
|
||||
Ollama runs locally with GPU acceleration for tasks that don't need Claude-level reasoning.
|
||||
|
||||
| Model | Size | Use For |
|
||||
|-------|------|---------|
|
||||
| `qwen3:14b` | 9.3 GB | Summarization, classification, data extraction, drafting |
|
||||
| `codestral:22b` | 12 GB | Code generation, refactoring suggestions, docstrings |
|
||||
| `nomic-embed-text` | 274 MB | Embeddings only (used by GrepAI) |
|
||||
|
||||
```bash
|
||||
# Simple prompt
|
||||
curl -s http://localhost:11434/api/generate -d '{"model":"qwen3:14b","prompt":"...","stream":false}' | jq -r '.response'
|
||||
```
|
||||
|
||||
**Review policy:** Always review Critical/High impact Ollama outputs (auth, security, migrations, production). Trust Low impact (classification, formatting). Flag uncertainty to user.
|
||||
|
||||
### GrepAI (Semantic Code Search)
|
||||
|
||||
Use for intent-based search ("how does auth work"), exploring unfamiliar code, context recovery.
|
||||
- **MCP tool:** `grepai` server tools
|
||||
- **Agent:** `deep-explore` agent
|
||||
- **CLI:** `grepai search "query" --json --compact`
|
||||
|
||||
---
|
||||
|
||||
## Memory (Shared Across Machines)
|
||||
|
||||
Stored in-repo at `.claude/memory/` -- syncs via Gitea to all workstations.
|
||||
Index: `.claude/memory/MEMORY.md`
|
||||
|
||||
**IMPORTANT:** Always write to `.claude/memory/` (repo-relative), NOT `~/.claude/projects/*/memory/`.
|
||||
|
||||
---
|
||||
|
||||
## Reference (read on-demand)
|
||||
|
||||
- **Project structure, endpoints, workflows:** `.claude/REFERENCE.md`
|
||||
- **Agent definitions:** `.claude/agents/*.md`
|
||||
- **MCP servers:** `MCP_SERVERS.md`
|
||||
- **Coding standards:** `.claude/CODING_GUIDELINES.md`
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2026-04-02
|
||||
@@ -1,364 +1,57 @@
|
||||
# ClaudeTools - Coding Guidelines
|
||||
|
||||
## General Principles
|
||||
|
||||
These guidelines ensure code quality, consistency, and maintainability across the ClaudeTools project.
|
||||
Project-specific standards. Generic language conventions (PEP 8, etc.) are assumed knowledge.
|
||||
|
||||
---
|
||||
|
||||
## Character Encoding and Text
|
||||
## Character Encoding
|
||||
|
||||
### NO EMOJIS - EVER
|
||||
|
||||
**Rule:** Never use emojis in any code files, including:
|
||||
- Python scripts (.py)
|
||||
- PowerShell scripts (.ps1)
|
||||
- Bash scripts (.sh)
|
||||
- Configuration files
|
||||
- Documentation within code
|
||||
- Log messages
|
||||
- Output strings
|
||||
Never use emojis in code, scripts, config files, log messages, or output strings.
|
||||
|
||||
**Rationale:**
|
||||
- Emojis cause encoding issues (UTF-8 vs ASCII)
|
||||
- PowerShell parsing errors with special Unicode characters
|
||||
- Cross-platform compatibility problems
|
||||
- Terminal rendering inconsistencies
|
||||
- Version control diff issues
|
||||
**Rationale:** Causes PowerShell parsing errors, encoding issues, terminal rendering problems.
|
||||
|
||||
**Instead of emojis, use:**
|
||||
```powershell
|
||||
# BAD - causes parsing errors
|
||||
Write-Host "✓ Success!"
|
||||
Write-Host "⚠ Warning!"
|
||||
|
||||
# GOOD - ASCII text markers
|
||||
Write-Host "[OK] Success!"
|
||||
Write-Host "[SUCCESS] Task completed!"
|
||||
Write-Host "[WARNING] Check settings!"
|
||||
Write-Host "[ERROR] Failed to connect!"
|
||||
**Use instead:**
|
||||
```
|
||||
[OK] [SUCCESS] [INFO] [WARNING] [ERROR] [CRITICAL]
|
||||
```
|
||||
|
||||
**Allowed in:**
|
||||
- User-facing web UI (where Unicode is properly handled)
|
||||
- Database content (with proper UTF-8 encoding)
|
||||
- Markdown documentation (README.md, etc.) - use sparingly
|
||||
**Exception:** User-facing web UI with proper UTF-8 handling.
|
||||
|
||||
---
|
||||
|
||||
## Python Code Standards
|
||||
## Naming Conventions
|
||||
|
||||
### Style
|
||||
- Follow PEP 8 style guide
|
||||
- Use 4 spaces for indentation (no tabs)
|
||||
- Maximum line length: 100 characters (relaxed from 79)
|
||||
- Use type hints for function parameters and return values
|
||||
|
||||
### Imports
|
||||
```python
|
||||
# Standard library imports
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
# Third-party imports
|
||||
from fastapi import FastAPI
|
||||
from sqlalchemy import Column
|
||||
|
||||
# Local imports
|
||||
from api.models import User
|
||||
from api.utils import encrypt_data
|
||||
```
|
||||
|
||||
### Naming Conventions
|
||||
- Classes: `PascalCase` (e.g., `UserService`, `CredentialModel`)
|
||||
- Functions/methods: `snake_case` (e.g., `get_user`, `create_session`)
|
||||
- Constants: `UPPER_SNAKE_CASE` (e.g., `API_BASE_URL`, `MAX_RETRIES`)
|
||||
- Private methods: `_leading_underscore` (e.g., `_internal_helper`)
|
||||
- **Python:** snake_case functions, PascalCase classes, UPPER_SNAKE constants
|
||||
- **PowerShell:** PascalCase variables ($TaskName), approved verbs (Get-/Set-/New-)
|
||||
- **Bash:** lowercase_underscore functions, quote all variables
|
||||
- **DB tables:** lowercase plural (users, user_sessions), FK as {table}_id
|
||||
- **DB columns:** created_at/updated_at timestamps, is_/has_ boolean prefixes
|
||||
|
||||
---
|
||||
|
||||
## PowerShell Code Standards
|
||||
## Security
|
||||
|
||||
### Style
|
||||
- Use 4 spaces for indentation
|
||||
- Use PascalCase for variables: `$TaskName`, `$PythonPath`
|
||||
- Use approved verbs for functions: `Get-`, `Set-`, `New-`, `Remove-`
|
||||
|
||||
### Error Handling
|
||||
```powershell
|
||||
# Always use -ErrorAction for cmdlets that might fail
|
||||
$Task = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue
|
||||
if (-not $Task) {
|
||||
Write-Host "[ERROR] Task not found"
|
||||
exit 1
|
||||
}
|
||||
```
|
||||
|
||||
### Output
|
||||
```powershell
|
||||
# Use clear status markers
|
||||
Write-Host "[INFO] Starting process..."
|
||||
Write-Host "[SUCCESS] Task completed"
|
||||
Write-Host "[ERROR] Failed to connect"
|
||||
Write-Host "[WARNING] Configuration missing"
|
||||
```
|
||||
- Never hardcode credentials -- use SOPS vault or environment variables
|
||||
- JWT tokens for API auth, Argon2 for password hashing
|
||||
- Log all authentication attempts and sensitive operations
|
||||
- `.env` files are gitignored, never committed
|
||||
|
||||
---
|
||||
|
||||
## Bash Script Standards
|
||||
## API Standards
|
||||
|
||||
### Style
|
||||
- Use 2 spaces for indentation
|
||||
- Always use `#!/bin/bash` shebang
|
||||
- Quote all variables: `"$variable"` not `$variable`
|
||||
- Use `set -e` for error handling (exit on error)
|
||||
|
||||
### Functions
|
||||
```bash
|
||||
# Use lowercase with underscores
|
||||
function check_connection() {
|
||||
local host="$1"
|
||||
echo "[INFO] Checking connection to $host"
|
||||
}
|
||||
```
|
||||
- RESTful with plural nouns: `/api/users`
|
||||
- Consistent error format: `{"detail": "...", "error_code": "...", "status_code": N}`
|
||||
- Paginate large result sets
|
||||
- Document with OpenAPI (automatic with FastAPI)
|
||||
|
||||
---
|
||||
|
||||
## API Development Standards
|
||||
## Output Markers
|
||||
|
||||
### Endpoints
|
||||
- Use RESTful conventions
|
||||
- Use plural nouns: `/api/users` not `/api/user`
|
||||
- Use HTTP methods appropriately: GET, POST, PUT, DELETE
|
||||
- Version APIs if breaking changes: `/api/v2/users`
|
||||
|
||||
### Error Responses
|
||||
```python
|
||||
# Return consistent error format
|
||||
{
|
||||
"detail": "User not found",
|
||||
"error_code": "USER_NOT_FOUND",
|
||||
"status_code": 404
|
||||
}
|
||||
```
|
||||
|
||||
### Documentation
|
||||
- Every endpoint must have a docstring
|
||||
- Use Pydantic schemas for request/response validation
|
||||
- Document in OpenAPI (automatic with FastAPI)
|
||||
|
||||
---
|
||||
|
||||
## Database Standards
|
||||
|
||||
### Table Naming
|
||||
- Use lowercase with underscores: `user_sessions`, `billable_time`
|
||||
- Use plural nouns: `users` not `user`
|
||||
- Use consistent prefixes for related tables
|
||||
|
||||
### Columns
|
||||
- Primary key: `id` (UUID)
|
||||
- Timestamps: `created_at`, `updated_at`
|
||||
- Foreign keys: `{table}_id` (e.g., `user_id`, `project_id`)
|
||||
- Boolean: `is_active`, `has_access` (prefix with is_/has_)
|
||||
|
||||
### Indexes
|
||||
```python
|
||||
# Add indexes for frequently queried fields
|
||||
Index('idx_users_email', 'email')
|
||||
Index('idx_sessions_project_id', 'project_id')
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Standards
|
||||
|
||||
### Credentials
|
||||
- Never hardcode credentials in code
|
||||
- Use environment variables for sensitive data
|
||||
- Use `.env` files (gitignored) for local development
|
||||
- Encrypt passwords with AES-256-GCM (Fernet)
|
||||
|
||||
### Authentication
|
||||
- Use JWT tokens for API authentication
|
||||
- Hash passwords with Argon2
|
||||
- Include token expiration
|
||||
- Log all authentication attempts
|
||||
|
||||
### Audit Logging
|
||||
```python
|
||||
# Log all sensitive operations
|
||||
audit_log = CredentialAuditLog(
|
||||
credential_id=credential.id,
|
||||
action="password_updated",
|
||||
user_id=current_user.id,
|
||||
details="Password updated via API"
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Standards
|
||||
|
||||
### Test Files
|
||||
- Name: `test_{module_name}.py`
|
||||
- Location: Same directory as code being tested
|
||||
- Use pytest framework
|
||||
|
||||
### Test Structure
|
||||
```python
|
||||
def test_create_user():
|
||||
"""Test user creation with valid data."""
|
||||
# Arrange
|
||||
user_data = {"email": "test@example.com", "name": "Test"}
|
||||
|
||||
# Act
|
||||
result = create_user(user_data)
|
||||
|
||||
# Assert
|
||||
assert result.email == "test@example.com"
|
||||
assert result.id is not None
|
||||
```
|
||||
|
||||
### Coverage
|
||||
- Aim for 80%+ code coverage
|
||||
- Test happy path and error cases
|
||||
- Mock external dependencies (database, APIs)
|
||||
|
||||
---
|
||||
|
||||
## Git Commit Standards
|
||||
|
||||
### Commit Messages
|
||||
```
|
||||
[Type] Brief description (50 chars max)
|
||||
|
||||
Detailed explanation if needed (wrap at 72 chars)
|
||||
|
||||
- Change 1
|
||||
- Change 2
|
||||
- Change 3
|
||||
```
|
||||
|
||||
### Types
|
||||
- `[Feature]` - New feature
|
||||
- `[Fix]` - Bug fix
|
||||
- `[Refactor]` - Code refactoring
|
||||
- `[Docs]` - Documentation only
|
||||
- `[Test]` - Test updates
|
||||
- `[Config]` - Configuration changes
|
||||
|
||||
---
|
||||
|
||||
## File Organization
|
||||
|
||||
### Directory Structure
|
||||
```
|
||||
project/
|
||||
├── api/ # API application code
|
||||
│ ├── models/ # Database models
|
||||
│ ├── routers/ # API endpoints
|
||||
│ ├── schemas/ # Pydantic schemas
|
||||
│ ├── services/ # Business logic
|
||||
│ └── utils/ # Helper functions
|
||||
├── .claude/ # Claude Code configuration
|
||||
│ ├── hooks/ # Git-style hooks
|
||||
│ └── agents/ # Agent instructions
|
||||
├── scripts/ # Utility scripts
|
||||
└── migrations/ # Database migrations
|
||||
```
|
||||
|
||||
### File Naming
|
||||
- Python: `snake_case.py`
|
||||
- Classes: Match class name (e.g., `UserService` in `user_service.py`)
|
||||
- Scripts: Descriptive names (e.g., `setup_database.sh`, `test_api.py`)
|
||||
|
||||
---
|
||||
|
||||
## Documentation Standards
|
||||
|
||||
### Code Comments
|
||||
```python
|
||||
# Use comments for WHY, not WHAT
|
||||
# Good: "Retry 3 times to handle transient network errors"
|
||||
# Bad: "Set retry count to 3"
|
||||
|
||||
def fetch_data(url: str) -> dict:
|
||||
"""
|
||||
Fetch data from API endpoint.
|
||||
|
||||
Args:
|
||||
url: Full URL to fetch from
|
||||
|
||||
Returns:
|
||||
Parsed JSON response
|
||||
|
||||
Raises:
|
||||
ConnectionError: If API is unreachable
|
||||
ValueError: If response is invalid JSON
|
||||
"""
|
||||
```
|
||||
|
||||
### README Files
|
||||
- Include quick start guide
|
||||
- Document prerequisites
|
||||
- Provide examples
|
||||
- Keep up to date
|
||||
|
||||
---
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Python
|
||||
```python
|
||||
# Use specific exceptions
|
||||
try:
|
||||
result = api_call()
|
||||
except ConnectionError as e:
|
||||
logger.error(f"[ERROR] Connection failed: {e}")
|
||||
raise
|
||||
except ValueError as e:
|
||||
logger.warning(f"[WARNING] Invalid data: {e}")
|
||||
return None
|
||||
```
|
||||
|
||||
### PowerShell
|
||||
```powershell
|
||||
# Use try/catch for error handling
|
||||
try {
|
||||
$Result = Invoke-RestMethod -Uri $Url
|
||||
} catch {
|
||||
Write-Host "[ERROR] Request failed: $_"
|
||||
exit 1
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Logging Standards
|
||||
|
||||
### Log Levels
|
||||
- `DEBUG` - Detailed diagnostic info (development only)
|
||||
- `INFO` - General informational messages
|
||||
- `WARNING` - Warning messages (non-critical issues)
|
||||
- `ERROR` - Error messages (failures)
|
||||
- `CRITICAL` - Critical errors (system failures)
|
||||
|
||||
### Log Format
|
||||
```python
|
||||
# Use structured logging
|
||||
logger.info(
|
||||
"[INFO] User login",
|
||||
extra={
|
||||
"user_id": user.id,
|
||||
"ip_address": request.client.host,
|
||||
"timestamp": datetime.utcnow()
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### Output Markers
|
||||
All scripts and tools use ASCII status markers:
|
||||
```
|
||||
[INFO] Starting process
|
||||
[SUCCESS] Task completed
|
||||
@@ -369,60 +62,12 @@ logger.info(
|
||||
|
||||
---
|
||||
|
||||
## Performance Guidelines
|
||||
## Git
|
||||
|
||||
### Database Queries
|
||||
- Use indexes for frequently queried fields
|
||||
- Avoid N+1 queries (use joins or eager loading)
|
||||
- Paginate large result sets
|
||||
- Use connection pooling
|
||||
|
||||
### API Responses
|
||||
- Return only necessary fields
|
||||
- Use pagination for lists
|
||||
- Compress large payloads
|
||||
- Cache frequently accessed data
|
||||
|
||||
### File Operations
|
||||
- Use context managers (`with` statements)
|
||||
- Stream large files (don't load into memory)
|
||||
- Clean up temporary files
|
||||
- Commit types: feat, fix, refactor, docs, test, config
|
||||
- Always include `Co-Authored-By` line for Claude commits
|
||||
- Never commit .env, credentials, venv, __pycache__, *.log
|
||||
|
||||
---
|
||||
|
||||
## Version Control
|
||||
|
||||
### .gitignore
|
||||
Always exclude:
|
||||
- `.env` files (credentials)
|
||||
- `__pycache__/` (Python cache)
|
||||
- `*.pyc` (compiled Python)
|
||||
- `.venv/`, `venv/` (virtual environments)
|
||||
- `.claude/*.json` (local state)
|
||||
- `*.log` (log files)
|
||||
|
||||
### Branching
|
||||
- `main` - Production-ready code
|
||||
- `develop` - Integration branch
|
||||
- `feature/*` - New features
|
||||
- `fix/*` - Bug fixes
|
||||
- `hotfix/*` - Urgent production fixes
|
||||
|
||||
---
|
||||
|
||||
## Review Checklist
|
||||
|
||||
Before committing code, verify:
|
||||
- [ ] No emojis or special Unicode characters
|
||||
- [ ] All variables and functions have descriptive names
|
||||
- [ ] No hardcoded credentials or sensitive data
|
||||
- [ ] Error handling is implemented
|
||||
- [ ] Code is formatted consistently
|
||||
- [ ] Tests pass (if applicable)
|
||||
- [ ] Documentation is updated
|
||||
- [ ] No debugging print statements left in code
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2026-01-17
|
||||
**Status:** Active
|
||||
**Last Updated:** 2026-04-02
|
||||
|
||||
@@ -1,418 +0,0 @@
|
||||
# Directives Enforcement Mechanism
|
||||
|
||||
**Created:** 2026-01-19
|
||||
**Purpose:** Ensure Claude consistently follows operational directives and stops taking shortcuts
|
||||
|
||||
---
|
||||
|
||||
## The Problem
|
||||
|
||||
Claude (Main Instance) has a tendency to:
|
||||
- Take shortcuts by querying database directly instead of using Database Agent
|
||||
- Use emojis despite explicit prohibition (causes PowerShell errors)
|
||||
- Execute operations directly instead of coordinating via agents
|
||||
- Forget directives after conversation compaction or long sessions
|
||||
|
||||
**Result:** Violated architecture, broken scripts, inconsistent behavior
|
||||
|
||||
---
|
||||
|
||||
## The Solution: Multi-Layered Enforcement
|
||||
|
||||
### Layer 1: Prominent Directive Reference in claude.md
|
||||
|
||||
**File:** `.claude/claude.md` (line 3-15)
|
||||
|
||||
```markdown
|
||||
**FIRST: READ YOUR DIRECTIVES**
|
||||
|
||||
Before doing ANYTHING in this project, read and internalize `directives.md` in the project root.
|
||||
|
||||
This file defines:
|
||||
- Your identity (Coordinator, not Executor)
|
||||
- What you DO and DO NOT do
|
||||
- Agent coordination rules (NEVER query database directly)
|
||||
- Enforcement checklist (NO EMOJIS, ASCII markers only)
|
||||
|
||||
**If you haven't read directives.md in this session, STOP and read it now.**
|
||||
|
||||
Command: `Read directives.md` (in project root: D:\ClaudeTools\directives.md)
|
||||
```
|
||||
|
||||
**Effect:** First thing Claude sees when loading project context
|
||||
|
||||
---
|
||||
|
||||
### Layer 2: /refresh-directives Command
|
||||
|
||||
**File:** `.claude/commands/refresh-directives.md`
|
||||
|
||||
**Purpose:** Command to re-read and internalize directives
|
||||
|
||||
**User invocation:**
|
||||
```
|
||||
/refresh-directives
|
||||
```
|
||||
|
||||
**Auto-invocation points:**
|
||||
- After `/checkpoint` command
|
||||
- After `/save` command
|
||||
- After conversation compaction (detected automatically)
|
||||
- After large task completion (3+ agents)
|
||||
- Every 50 tool uses (optional counter-based)
|
||||
|
||||
**What it does:**
|
||||
1. Reads `directives.md` completely
|
||||
2. Performs self-assessment for violations
|
||||
3. Commits to following directives
|
||||
4. Reports status to user
|
||||
|
||||
**Output:**
|
||||
```markdown
|
||||
## Directives Refreshed
|
||||
|
||||
I've re-read my operational directives.
|
||||
|
||||
**Key commitments:**
|
||||
- [OK] Coordinate via agents, not execute
|
||||
- [OK] Database Agent for ALL data operations
|
||||
- [OK] ASCII markers only (no emojis)
|
||||
- [OK] Preserve context by delegating
|
||||
|
||||
**Self-assessment:** Clean - no violations detected
|
||||
|
||||
**Status:** Ready to coordinate effectively.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Layer 3: Integration with /checkpoint Command
|
||||
|
||||
**File:** `.claude/commands/checkpoint.md` (step 8)
|
||||
|
||||
**After git + database checkpoint:**
|
||||
```markdown
|
||||
8. **Refresh directives** (MANDATORY):
|
||||
- After checkpoint completion, auto-invoke `/refresh-directives`
|
||||
- Re-read `directives.md` to prevent shortcut-taking
|
||||
- Perform self-assessment for any violations
|
||||
- Confirm commitment to agent coordination rules
|
||||
- Report directives refreshed to user
|
||||
```
|
||||
|
||||
**Effect:** Every checkpoint automatically refreshes directives
|
||||
|
||||
---
|
||||
|
||||
### Layer 4: Integration with /save Command
|
||||
|
||||
**File:** `.claude/commands/save.md` (step 4)
|
||||
|
||||
**After saving session log:**
|
||||
```markdown
|
||||
4. **Refresh directives** (MANDATORY):
|
||||
- Auto-invoke `/refresh-directives`
|
||||
- Re-read `directives.md` to prevent shortcut-taking
|
||||
- Perform self-assessment for violations
|
||||
- Confirm commitment to coordination rules
|
||||
- Report directives refreshed
|
||||
```
|
||||
|
||||
**Effect:** Every session save automatically refreshes directives
|
||||
|
||||
---
|
||||
|
||||
### Layer 5: directives.md (The Source of Truth)
|
||||
|
||||
**File:** `directives.md` (project root)
|
||||
|
||||
**Contains:**
|
||||
- Identity definition (Coordinator, not Executor)
|
||||
- What Claude DOES and DOES NOT do
|
||||
- Complete agent coordination rules
|
||||
- Coding standards (NO EMOJIS - ASCII only)
|
||||
- Enforcement checklist
|
||||
- Pre-action verification questions
|
||||
|
||||
**Key sections:**
|
||||
1. My Identity
|
||||
2. Core Operating Principle
|
||||
3. What I DO [OK]
|
||||
4. What I DO NOT DO [ERROR]
|
||||
5. Agent Coordination Rules
|
||||
6. Skills vs Agents
|
||||
7. Automatic Behaviors
|
||||
8. Coding Standards (NO EMOJIS)
|
||||
9. Enforcement Checklist
|
||||
|
||||
---
|
||||
|
||||
## Automatic Trigger Points
|
||||
|
||||
### Session Start
|
||||
```
|
||||
Claude loads project → Sees claude.md → "READ DIRECTIVES FIRST"
|
||||
→ Reads directives.md → Internalizes rules → Ready to work
|
||||
```
|
||||
|
||||
### After Checkpoint
|
||||
```
|
||||
User: /checkpoint
|
||||
→ Claude creates git commit + database context
|
||||
→ Verifies both succeeded
|
||||
→ AUTO-INVOKES /refresh-directives
|
||||
→ Re-reads directives.md
|
||||
→ Confirms ready to proceed
|
||||
```
|
||||
|
||||
### After Save
|
||||
```
|
||||
User: /save
|
||||
→ Claude creates/updates session log
|
||||
→ Commits to repository
|
||||
→ AUTO-INVOKES /refresh-directives
|
||||
→ Re-reads directives.md
|
||||
→ Confirms ready to proceed
|
||||
```
|
||||
|
||||
### After Conversation Compaction
|
||||
```
|
||||
System: [Conversation compacted due to length]
|
||||
→ Claude detects compaction (system message)
|
||||
→ AUTO-INVOKES /refresh-directives
|
||||
→ Re-reads directives.md
|
||||
→ Restores operational mode
|
||||
→ Continues with proper coordination
|
||||
```
|
||||
|
||||
### After Large Task
|
||||
```
|
||||
Claude completes task using 3+ agents
|
||||
→ Recognizes major work completed
|
||||
→ AUTO-INVOKES /refresh-directives
|
||||
→ Re-reads directives.md
|
||||
→ Resets to coordination mode
|
||||
→ Ready for next task
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Violation Detection
|
||||
|
||||
### Self-Assessment Process
|
||||
|
||||
**During /refresh-directives, Claude checks:**
|
||||
|
||||
**Database Operations:**
|
||||
- [ ] Did I query database directly via ssh/mysql/curl? → VIOLATION
|
||||
- [ ] Did I call ClaudeTools API directly? → VIOLATION
|
||||
- [ ] Did I use Database Agent for data operations? → CORRECT
|
||||
|
||||
**Code Generation:**
|
||||
- [ ] Did I write production code myself? → VIOLATION
|
||||
- [ ] Did I delegate to Coding Agent? → CORRECT
|
||||
|
||||
**Emoji Usage:**
|
||||
- [ ] Did I use [OK][ERROR][WARNING] or other emojis? → VIOLATION
|
||||
- [ ] Did I use [OK]/[ERROR]/[WARNING]? → CORRECT
|
||||
|
||||
**Agent Coordination:**
|
||||
- [ ] Did I execute operations directly? → VIOLATION
|
||||
- [ ] Did I coordinate via agents? → CORRECT
|
||||
|
||||
**If violations detected:**
|
||||
```markdown
|
||||
[WARNING] Detected 2 directive violations:
|
||||
- Direct database query at timestamp X
|
||||
- Emoji usage in output at timestamp Y
|
||||
|
||||
[OK] Corrective actions committed:
|
||||
- Will use Database Agent for all database operations
|
||||
- Will use ASCII markers [OK]/[ERROR] instead of emojis
|
||||
|
||||
[SUCCESS] Directives re-internalized. Proper coordination restored.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Benefits
|
||||
|
||||
### Prevents Shortcut-Taking
|
||||
- Regular reminders not to query database directly
|
||||
- Reinforces agent coordination model
|
||||
- Stops emoji usage before it causes errors
|
||||
|
||||
### Context Recovery
|
||||
- Restores operational mode after compaction
|
||||
- Ensures consistency across sessions
|
||||
- Maintains proper coordination principles
|
||||
|
||||
### Self-Correction
|
||||
- Detects violations automatically
|
||||
- Commits to corrective behavior
|
||||
- Provides accountability to user
|
||||
|
||||
### User Visibility
|
||||
- User sees when directives refreshed
|
||||
- Transparent operational changes
|
||||
- Builds trust in coordination model
|
||||
|
||||
---
|
||||
|
||||
## Enforcement Checklist
|
||||
|
||||
### For Claude (Self-Check Before Any Action)
|
||||
|
||||
**Before database operation:**
|
||||
- [ ] Read directives.md this session? If no → STOP and read
|
||||
- [ ] Am I about to query database? → Use Database Agent instead
|
||||
- [ ] Am I about to use curl/API? → Use Database Agent instead
|
||||
|
||||
**Before writing code:**
|
||||
- [ ] Am I writing production code? → Delegate to Coding Agent
|
||||
- [ ] Am I using emojis? → STOP, use [OK]/[ERROR]/[WARNING]
|
||||
|
||||
**Before git operations:**
|
||||
- [ ] Am I about to commit? → Delegate to Gitea Agent
|
||||
- [ ] Am I about to push? → Delegate to Gitea Agent
|
||||
|
||||
**After major operations:**
|
||||
- [ ] Completed checkpoint/save? → Auto-invoke /refresh-directives
|
||||
- [ ] Completed large task? → Auto-invoke /refresh-directives
|
||||
- [ ] Conversation compacted? → Auto-invoke /refresh-directives
|
||||
|
||||
---
|
||||
|
||||
## User Commands
|
||||
|
||||
### Manual Refresh
|
||||
```
|
||||
/refresh-directives
|
||||
```
|
||||
Manually trigger directive re-reading and self-assessment
|
||||
|
||||
### Checkpoint (Auto-refresh)
|
||||
```
|
||||
/checkpoint
|
||||
```
|
||||
Creates git commit + database context, then auto-refreshes directives
|
||||
|
||||
### Save (Auto-refresh)
|
||||
```
|
||||
/save
|
||||
```
|
||||
Creates session log, then auto-refreshes directives
|
||||
|
||||
### Sync
|
||||
```
|
||||
/sync
|
||||
```
|
||||
Pulls latest from Gitea (directives.md included if updated)
|
||||
|
||||
---
|
||||
|
||||
## Monitoring
|
||||
|
||||
### User Can Monitor Compliance
|
||||
|
||||
**Check for violations:**
|
||||
- Look for direct `ssh`, `mysql`, or `curl` commands to database
|
||||
- Look for emoji characters ([OK][ERROR][WARNING]) in output
|
||||
- Look for direct code generation (should delegate to Coding Agent)
|
||||
|
||||
**If violations detected:**
|
||||
```
|
||||
User: /refresh-directives
|
||||
```
|
||||
Forces Claude to re-read and commit to directives
|
||||
|
||||
---
|
||||
|
||||
## Maintenance
|
||||
|
||||
### Updating directives.md
|
||||
|
||||
**When to update:**
|
||||
- New agent added to system
|
||||
- New restriction discovered
|
||||
- Behavior patterns change
|
||||
- New shortcut tendencies identified
|
||||
|
||||
**Process:**
|
||||
1. Edit `directives.md` with new rules
|
||||
2. Commit changes to repository
|
||||
3. Push to Gitea
|
||||
4. Invoke `/sync` on other machines
|
||||
5. Invoke `/refresh-directives` to apply immediately
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
**Five-layer enforcement:**
|
||||
1. **claude.md** - Prominent reference at top (first thing Claude sees)
|
||||
2. **/refresh-directives command** - Explicit directive re-reading
|
||||
3. **/checkpoint integration** - Auto-refresh after checkpoints
|
||||
4. **/save integration** - Auto-refresh after session saves
|
||||
5. **directives.md** - Complete operational ruleset
|
||||
|
||||
**Automatic triggers:**
|
||||
- Session start
|
||||
- After /checkpoint
|
||||
- After /save
|
||||
- After conversation compaction
|
||||
- After large tasks
|
||||
|
||||
**Result:** Claude consistently follows directives, stops taking shortcuts, maintains proper agent coordination architecture.
|
||||
|
||||
---
|
||||
|
||||
## Example: Full Enforcement Flow
|
||||
|
||||
```
|
||||
Session Start:
|
||||
→ Claude loads .claude/claude.md
|
||||
→ Sees "READ YOUR DIRECTIVES FIRST"
|
||||
→ Reads directives.md completely
|
||||
→ Internalizes rules
|
||||
→ Ready to coordinate (not execute)
|
||||
|
||||
User Request:
|
||||
→ "How many projects in database?"
|
||||
→ Claude recognizes database operation
|
||||
→ Checks directives: "Database Agent handles ALL database operations"
|
||||
→ Launches Database Agent with task
|
||||
→ Receives count from agent
|
||||
→ Presents to user
|
||||
|
||||
After /checkpoint:
|
||||
→ Git commit created
|
||||
→ Database context saved
|
||||
→ AUTO-INVOKES /refresh-directives
|
||||
→ Re-reads directives.md
|
||||
→ Self-assessment: Clean
|
||||
→ Confirms: "Directives refreshed. Ready to coordinate."
|
||||
|
||||
Conversation Compacted:
|
||||
→ System compacts conversation
|
||||
→ Claude detects compaction
|
||||
→ AUTO-INVOKES /refresh-directives
|
||||
→ Re-reads directives.md
|
||||
→ Restores coordination mode
|
||||
→ Continues properly
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**This enforcement mechanism ensures Claude maintains proper operational behavior throughout the entire session lifecycle.**
|
||||
|
||||
---
|
||||
|
||||
**Created:** 2026-01-19
|
||||
**Files Modified:**
|
||||
- `.claude/claude.md` - Added directive reference at top
|
||||
- `.claude/commands/checkpoint.md` - Added step 8 (refresh directives)
|
||||
- `.claude/commands/save.md` - Added step 4 (refresh directives)
|
||||
- `.claude/commands/refresh-directives.md` - New command definition
|
||||
|
||||
**Status:** Active enforcement system
|
||||
213
.claude/REFERENCE.md
Normal file
213
.claude/REFERENCE.md
Normal file
@@ -0,0 +1,213 @@
|
||||
# ClaudeTools Reference Guide
|
||||
|
||||
**Purpose:** On-demand reference material for agents and deep-dive questions.
|
||||
**Not loaded automatically** - agents read this when they need project details.
|
||||
|
||||
---
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
D:\ClaudeTools/
|
||||
├── api/ # FastAPI application
|
||||
│ ├── main.py # API entry point
|
||||
│ ├── models/ # SQLAlchemy models
|
||||
│ ├── routers/ # API endpoints
|
||||
│ ├── schemas/ # Pydantic schemas
|
||||
│ ├── services/ # Business logic
|
||||
│ ├── middleware/ # Auth & error handling
|
||||
│ └── utils/ # Crypto utilities
|
||||
├── migrations/ # Alembic database migrations
|
||||
├── .claude/ # Claude Code hooks & config
|
||||
│ ├── commands/ # Commands (create-spec, checkpoint)
|
||||
│ ├── skills/ # Skills (frontend-design)
|
||||
│ └── templates/ # Templates (app spec, prompts)
|
||||
├── mcp-servers/ # MCP server implementations
|
||||
│ └── feature-management/ # Feature tracking MCP server
|
||||
├── scripts/ # Setup & test scripts
|
||||
└── projects/ # Project workspaces
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Starting the API
|
||||
|
||||
```bash
|
||||
# Activate virtual environment
|
||||
api\venv\Scripts\activate
|
||||
|
||||
# Start API server
|
||||
python -m api.main
|
||||
# OR
|
||||
uvicorn api.main:app --reload --host 0.0.0.0 --port 8000
|
||||
|
||||
# Access documentation
|
||||
http://localhost:8000/api/docs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Core Entities (Phase 4)
|
||||
- `/api/machines` - Machine inventory
|
||||
- `/api/clients` - Client management
|
||||
- `/api/projects` - Project tracking
|
||||
- `/api/sessions` - Work sessions
|
||||
- `/api/tags` - Tagging system
|
||||
|
||||
### MSP Work Tracking (Phase 5)
|
||||
- `/api/work-items` - Work item tracking
|
||||
- `/api/tasks` - Task management
|
||||
- `/api/billable-time` - Time & billing
|
||||
|
||||
### Infrastructure (Phase 5)
|
||||
- `/api/sites` - Physical locations
|
||||
- `/api/infrastructure` - IT assets
|
||||
- `/api/services` - Application services
|
||||
- `/api/networks` - Network configs
|
||||
- `/api/firewall-rules` - Firewall documentation
|
||||
- `/api/m365-tenants` - M365 tenant management
|
||||
|
||||
### Credentials (Phase 5)
|
||||
- `/api/credentials` - Encrypted credential storage
|
||||
- `/api/credential-audit-logs` - Audit trail (read-only)
|
||||
- `/api/security-incidents` - Incident tracking
|
||||
|
||||
---
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### 1. Create New Project
|
||||
|
||||
```python
|
||||
POST /api/projects
|
||||
{
|
||||
"name": "New Website",
|
||||
"client_id": "client-uuid",
|
||||
"status": "planning"
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Track Work Session
|
||||
|
||||
```python
|
||||
# Create session
|
||||
POST /api/sessions
|
||||
{
|
||||
"project_id": "project-uuid",
|
||||
"machine_id": "machine-uuid",
|
||||
"started_at": "2026-01-16T10:00:00Z"
|
||||
}
|
||||
|
||||
# Log billable time
|
||||
POST /api/billable-time
|
||||
{
|
||||
"session_id": "session-uuid",
|
||||
"work_item_id": "work-item-uuid",
|
||||
"client_id": "client-uuid",
|
||||
"start_time": "2026-01-16T10:00:00Z",
|
||||
"end_time": "2026-01-16T12:00:00Z",
|
||||
"duration_hours": 2.0,
|
||||
"hourly_rate": 150.00,
|
||||
"total_amount": 300.00
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Store Encrypted Credential
|
||||
|
||||
```python
|
||||
POST /api/credentials
|
||||
{
|
||||
"credential_type": "api_key",
|
||||
"service_name": "OpenAI API",
|
||||
"username": "api_key",
|
||||
"password": "sk-1234567890", # Auto-encrypted
|
||||
"client_id": "client-uuid",
|
||||
"notes": "Production API key"
|
||||
}
|
||||
# Password automatically encrypted with AES-256-GCM
|
||||
# Audit log automatically created
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Important Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `SESSION_STATE.md` | Complete project history and status |
|
||||
| `credentials.md` | ALL infrastructure credentials (UNREDACTED) |
|
||||
| `session-logs/` | Daily session documentation |
|
||||
| `.env` / `.env.example` | Environment variables |
|
||||
| `test_api_endpoints.py` | Phase 4 tests |
|
||||
| `test_phase5_api_endpoints.py` | Phase 5 tests |
|
||||
| `AUTOCODER_INTEGRATION.md` | AutoCoder resources guide |
|
||||
| `TEST_PHASE5_RESULTS.md` | Phase 5 test results |
|
||||
|
||||
---
|
||||
|
||||
## Security
|
||||
|
||||
- **Authentication:** JWT tokens (Argon2 password hashing)
|
||||
- **Encryption:** AES-256-GCM (Fernet) for credentials
|
||||
- **Audit Logging:** All credential operations logged
|
||||
|
||||
```bash
|
||||
# Get JWT Token
|
||||
POST /api/auth/token
|
||||
{ "email": "user@example.com", "password": "your-password" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
```bash
|
||||
# API won't start - check port
|
||||
netstat -ano | findstr :8000
|
||||
# Check database connection
|
||||
python test_db_connection.py
|
||||
|
||||
# Database migration issues
|
||||
alembic current # Check current revision
|
||||
alembic history # Show migration history
|
||||
alembic upgrade head # Upgrade to latest
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MCP Servers
|
||||
|
||||
See `MCP_SERVERS.md` for complete details.
|
||||
|
||||
- **GitHub MCP** - Repository and PR management (requires token)
|
||||
- **Filesystem MCP** - Enhanced file operations (D:\ClaudeTools access)
|
||||
- **Sequential Thinking MCP** - Structured problem-solving
|
||||
|
||||
Config: `.mcp.json` | Setup: `bash scripts/setup-mcp-servers.sh`
|
||||
|
||||
---
|
||||
|
||||
## Next Steps (Optional Phase 7)
|
||||
|
||||
- File Changes API - Track file modifications
|
||||
- Command Runs API - Command execution history
|
||||
- Problem Solutions API - Knowledge base
|
||||
- Failure Patterns API - Error pattern recognition
|
||||
- Environmental Insights API - Contextual learning
|
||||
|
||||
These are optional - the system is fully functional without them.
|
||||
|
||||
---
|
||||
|
||||
## Session Log Locations
|
||||
|
||||
**Project-Specific:**
|
||||
- Dataforth DOS: `projects/dataforth-dos/session-logs/YYYY-MM-DD-session.md`
|
||||
- ClaudeTools API: `projects/claudetools-api/session-logs/YYYY-MM-DD-session.md`
|
||||
|
||||
**Client-Specific:** `clients/[client-name]/session-logs/YYYY-MM-DD-session.md`
|
||||
**General/Mixed:** `session-logs/YYYY-MM-DD-session.md` (root)
|
||||
|
||||
See `PROJECT_ORGANIZATION.md` for complete structure.
|
||||
@@ -1,4 +1,66 @@
|
||||
{
|
||||
"last_updated": "2026-01-23T00:00:00Z",
|
||||
"tasks": []
|
||||
"last_updated": "2026-03-23T20:10:00Z",
|
||||
"tasks": [
|
||||
{
|
||||
"id": "win-setup-001",
|
||||
"title": "Windows Machine Setup - Align with Directives",
|
||||
"created": "2026-03-23",
|
||||
"status": "in_progress",
|
||||
"context": "Setting up Windows guru workstation to match ClaudeTools project directives. This session is non-elevated. Elevated session should pick up remaining items.",
|
||||
"completed_items": [
|
||||
"Node.js v24.14.0 installed via winget (PATH: C:\\Program Files\\nodejs)",
|
||||
".mcp.json created at C:\\Users\\guru\\ClaudeTools\\.mcp.json (filesystem + sequential-thinking)",
|
||||
"GrepAI v0.35.0 binary downloaded to C:\\Users\\guru\\ClaudeTools\\grepai.exe"
|
||||
],
|
||||
"remaining_items": [
|
||||
{
|
||||
"step": 1,
|
||||
"item": "Finish Ollama installation",
|
||||
"priority": "HIGH",
|
||||
"details": "winget install was downloading v0.18.2 (1.61GB) but session interrupted ~50%. Run: winget install Ollama.Ollama --accept-package-agreements --accept-source-agreements. Verify with: ollama --version"
|
||||
},
|
||||
{
|
||||
"step": 2,
|
||||
"item": "Pull Ollama models",
|
||||
"priority": "HIGH",
|
||||
"depends_on": "step 1",
|
||||
"details": "ollama pull nomic-embed-text && ollama pull qwen3:14b && ollama pull codestral:22b"
|
||||
},
|
||||
{
|
||||
"step": 3,
|
||||
"item": "Initialize GrepAI index",
|
||||
"priority": "HIGH",
|
||||
"depends_on": "step 2 (needs nomic-embed-text)",
|
||||
"details": "cd C:\\Users\\guru\\ClaudeTools && ./grepai.exe init && ./grepai.exe watch --background"
|
||||
},
|
||||
{
|
||||
"step": 4,
|
||||
"item": "Add GrepAI to .mcp.json",
|
||||
"priority": "HIGH",
|
||||
"depends_on": "step 3",
|
||||
"details": "Add to C:\\Users\\guru\\ClaudeTools\\.mcp.json mcpServers section: \"grepai\": { \"command\": \"C:\\\\Users\\\\guru\\\\ClaudeTools\\\\grepai.exe\", \"args\": [\"mcp-serve\"] }"
|
||||
},
|
||||
{
|
||||
"step": 5,
|
||||
"item": "Verify MCP servers load",
|
||||
"priority": "MEDIUM",
|
||||
"depends_on": "steps 1-4",
|
||||
"details": "Restart Claude Code and confirm sequential-thinking, filesystem, and grepai MCP servers connect. Node.js is installed but current shell may need PATH refresh."
|
||||
},
|
||||
{
|
||||
"step": 6,
|
||||
"item": "Update machine memory record",
|
||||
"priority": "LOW",
|
||||
"depends_on": "all above",
|
||||
"details": "Update .claude/memory/machine_windows_guru_setup_status.md to reflect completed setup. Remove all 'Missing' items, mark as fully aligned."
|
||||
}
|
||||
],
|
||||
"notes": [
|
||||
"GitHub MCP server intentionally excluded - project uses Gitea not GitHub",
|
||||
"User said they'll get back on git setup separately",
|
||||
"Node.js may not be in current shell PATH - new terminal needed",
|
||||
"Ollama download was partially through when interrupted"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
59
.claude/agents/deep-explore.md
Normal file
59
.claude/agents/deep-explore.md
Normal file
@@ -0,0 +1,59 @@
|
||||
---
|
||||
name: deep-explore
|
||||
description: Deep codebase exploration using grepai semantic search and call graph tracing. Use this agent for understanding code architecture, finding implementations by intent, analyzing function relationships, and exploring unfamiliar code areas.
|
||||
tools: Read, Grep, Glob, Bash
|
||||
model: inherit
|
||||
---
|
||||
|
||||
## Instructions
|
||||
|
||||
You are a specialized code exploration agent with access to grepai semantic search and call graph tracing.
|
||||
|
||||
### Primary Tools
|
||||
|
||||
#### 1. Semantic Search: `grepai search`
|
||||
|
||||
Use this to find code by intent and meaning:
|
||||
|
||||
```bash
|
||||
# Use English queries for best results (--compact saves ~80% tokens)
|
||||
grepai search "authentication flow" --json --compact
|
||||
grepai search "error handling middleware" --json --compact
|
||||
grepai search "database connection management" --json --compact
|
||||
```
|
||||
|
||||
#### 2. Call Graph Tracing: `grepai trace`
|
||||
|
||||
Use this to understand function relationships and code flow:
|
||||
|
||||
```bash
|
||||
# Find all functions that call a symbol
|
||||
grepai trace callers "HandleRequest" --json
|
||||
|
||||
# Find all functions called by a symbol
|
||||
grepai trace callees "ProcessOrder" --json
|
||||
|
||||
# Build complete call graph
|
||||
grepai trace graph "ValidateToken" --depth 3 --json
|
||||
```
|
||||
|
||||
Use `grepai trace` when you need to:
|
||||
- Find all callers of a function
|
||||
- Understand the call hierarchy
|
||||
- Analyze the impact of changes to a function
|
||||
- Map dependencies between components
|
||||
|
||||
### When to use standard tools
|
||||
|
||||
Only fall back to Grep/Glob when:
|
||||
- You need exact text matching (variable names, imports)
|
||||
- grepai is not available or returns errors
|
||||
- You need file path patterns
|
||||
|
||||
### Workflow
|
||||
|
||||
1. Start with `grepai search` to find relevant code semantically
|
||||
2. Use `grepai trace` to understand function relationships and call graphs
|
||||
3. Use `Read` to examine promising files in detail
|
||||
4. Use Grep only for exact string searches if needed
|
||||
5. Synthesize findings into a clear summary
|
||||
@@ -1,463 +0,0 @@
|
||||
# ClaudeTools Project Context
|
||||
|
||||
**FIRST: READ YOUR DIRECTIVES AND FILE PLACEMENT GUIDE**
|
||||
|
||||
Before doing ANYTHING in this project:
|
||||
1. Read and internalize `directives.md` in the project root
|
||||
2. Review `.claude/FILE_PLACEMENT_GUIDE.md` for file organization
|
||||
|
||||
**directives.md** defines:
|
||||
- Your identity (Coordinator, not Executor)
|
||||
- What you DO and DO NOT do
|
||||
- Agent coordination rules (NEVER query database directly)
|
||||
- Enforcement checklist (NO EMOJIS, ASCII markers only)
|
||||
|
||||
**FILE_PLACEMENT_GUIDE.md** defines:
|
||||
- Where to save new files (projects/ vs clients/ vs root)
|
||||
- Session log locations (project-specific vs general)
|
||||
- File naming conventions
|
||||
- Organization maintenance
|
||||
|
||||
**If you haven't read these in this session, STOP and read them now.**
|
||||
|
||||
Commands:
|
||||
- `Read directives.md` (in project root)
|
||||
- `Read .claude/FILE_PLACEMENT_GUIDE.md`
|
||||
|
||||
---
|
||||
|
||||
**Project Type:** MSP Work Tracking System
|
||||
**Status:** Production-Ready
|
||||
**Database:** MariaDB 10.6.22 @ 172.16.3.30:3306 (RMM Server)
|
||||
|
||||
---
|
||||
|
||||
## Quick Facts
|
||||
|
||||
- **95+ API Endpoints** across 17 entities
|
||||
- **38 Database Tables** (fully migrated)
|
||||
- **JWT Authentication** on all endpoints
|
||||
- **AES-256-GCM Encryption** for credentials
|
||||
- **3 MCP Servers** configured (GitHub, Filesystem, Sequential Thinking)
|
||||
|
||||
---
|
||||
|
||||
## Core Operating Principle: You Are a Coordinator
|
||||
|
||||
**CRITICAL:** Main Claude is a **coordinator**, not an executor. Your primary role is to delegate work to specialized agents and preserve your main context space.
|
||||
|
||||
**Main Context Space is Sacred:**
|
||||
- Your context window is valuable and limited
|
||||
- Delegate ALL significant operations to agents unless doing it yourself is significantly cheaper in tokens
|
||||
- Agents have their own full context windows for specialized tasks
|
||||
- Keep your context focused on coordination, decision-making, and user interaction
|
||||
|
||||
**When to Delegate (via Task tool):**
|
||||
- Database operations (queries, inserts, updates) → Database Agent
|
||||
- Code generation → Coding Agent
|
||||
- Code review → Code Review Agent (MANDATORY for all code)
|
||||
- Test execution → Testing Agent
|
||||
- Git operations → Gitea Agent
|
||||
- File exploration/search → Explore Agent
|
||||
- Complex problem-solving → General-purpose agent with Sequential Thinking MCP
|
||||
|
||||
**When to Do It Yourself:**
|
||||
- Simple user responses (conversational replies)
|
||||
- Reading a single file to answer a question
|
||||
- Basic file operations (1-2 files)
|
||||
- Presenting agent results to user
|
||||
- Making decisions about what to do next
|
||||
- Creating task checklists
|
||||
|
||||
**Example - Database Query (DELEGATE):**
|
||||
```
|
||||
User: "How many projects are in the database?"
|
||||
|
||||
[ERROR] WRONG: ssh guru@172.16.3.30 "mysql -u claudetools ... SELECT COUNT(*) ..."
|
||||
[OK] CORRECT: Launch Database Agent with task: "Count projects in database"
|
||||
```
|
||||
|
||||
**Example - Simple File Read (DO YOURSELF):**
|
||||
```
|
||||
User: "What's in the README?"
|
||||
|
||||
[OK] CORRECT: Use Read tool directly (cheap, preserves context)
|
||||
[ERROR] WRONG: Launch agent just to read one file (wasteful)
|
||||
```
|
||||
|
||||
**Rule of Thumb:**
|
||||
- If the operation will consume >500 tokens of your context → Delegate to agent
|
||||
- If it's a simple read/search/response → Do it yourself
|
||||
- If it's code generation or database work → ALWAYS delegate
|
||||
- When in doubt → Delegate (agents are cheap, your context is precious)
|
||||
|
||||
**See:** `.claude/AGENT_COORDINATION_RULES.md` for complete delegation guidelines
|
||||
|
||||
---
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
D:\ClaudeTools/
|
||||
├── api/ # FastAPI application
|
||||
│ ├── main.py # API entry point
|
||||
│ ├── models/ # SQLAlchemy models
|
||||
│ ├── routers/ # API endpoints
|
||||
│ ├── schemas/ # Pydantic schemas
|
||||
│ ├── services/ # Business logic
|
||||
│ ├── middleware/ # Auth & error handling
|
||||
│ └── utils/ # Crypto utilities
|
||||
├── migrations/ # Alembic database migrations
|
||||
├── .claude/ # Claude Code hooks & config
|
||||
│ ├── commands/ # Commands (create-spec, checkpoint)
|
||||
│ ├── skills/ # Skills (frontend-design)
|
||||
│ └── templates/ # Templates (app spec, prompts)
|
||||
├── mcp-servers/ # MCP server implementations
|
||||
│ └── feature-management/ # Feature tracking MCP server
|
||||
├── scripts/ # Setup & test scripts
|
||||
└── projects/ # Project workspaces
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Database Connection
|
||||
|
||||
**UPDATED 2026-01-17:** Database is centralized on RMM server (172.16.3.30)
|
||||
|
||||
**Connection String:**
|
||||
```
|
||||
Host: 172.16.3.30:3306
|
||||
Database: claudetools
|
||||
User: claudetools
|
||||
Password: CT_e8fcd5a3952030a79ed6debae6c954ed
|
||||
```
|
||||
|
||||
**Environment Variables:**
|
||||
```bash
|
||||
DATABASE_URL=mysql+pymysql://claudetools:CT_e8fcd5a3952030a79ed6debae6c954ed@172.16.3.30:3306/claudetools?charset=utf8mb4
|
||||
```
|
||||
|
||||
**API Base URL:** http://172.16.3.30:8001
|
||||
|
||||
**See:** `.claude/agents/DATABASE_CONNECTION_INFO.md` for complete details.
|
||||
|
||||
---
|
||||
|
||||
## Starting the API
|
||||
|
||||
```bash
|
||||
# Activate virtual environment
|
||||
api\venv\Scripts\activate
|
||||
|
||||
# Start API server
|
||||
python -m api.main
|
||||
# OR
|
||||
uvicorn api.main:app --reload --host 0.0.0.0 --port 8000
|
||||
|
||||
# Access documentation
|
||||
http://localhost:8000/api/docs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Key API Endpoints
|
||||
|
||||
### Core Entities (Phase 4)
|
||||
- `/api/machines` - Machine inventory
|
||||
- `/api/clients` - Client management
|
||||
- `/api/projects` - Project tracking
|
||||
- `/api/sessions` - Work sessions
|
||||
- `/api/tags` - Tagging system
|
||||
|
||||
### MSP Work Tracking (Phase 5)
|
||||
- `/api/work-items` - Work item tracking
|
||||
- `/api/tasks` - Task management
|
||||
- `/api/billable-time` - Time & billing
|
||||
|
||||
### Infrastructure (Phase 5)
|
||||
- `/api/sites` - Physical locations
|
||||
- `/api/infrastructure` - IT assets
|
||||
- `/api/services` - Application services
|
||||
- `/api/networks` - Network configs
|
||||
- `/api/firewall-rules` - Firewall documentation
|
||||
- `/api/m365-tenants` - M365 tenant management
|
||||
|
||||
### Credentials (Phase 5)
|
||||
- `/api/credentials` - Encrypted credential storage
|
||||
- `/api/credential-audit-logs` - Audit trail (read-only)
|
||||
- `/api/security-incidents` - Incident tracking
|
||||
|
||||
---
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### 1. Create New Project
|
||||
|
||||
```python
|
||||
# Create project
|
||||
POST /api/projects
|
||||
{
|
||||
"name": "New Website",
|
||||
"client_id": "client-uuid",
|
||||
"status": "planning"
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Track Work Session
|
||||
|
||||
```python
|
||||
# Create session
|
||||
POST /api/sessions
|
||||
{
|
||||
"project_id": "project-uuid",
|
||||
"machine_id": "machine-uuid",
|
||||
"started_at": "2026-01-16T10:00:00Z"
|
||||
}
|
||||
|
||||
# Log billable time
|
||||
POST /api/billable-time
|
||||
{
|
||||
"session_id": "session-uuid",
|
||||
"work_item_id": "work-item-uuid",
|
||||
"client_id": "client-uuid",
|
||||
"start_time": "2026-01-16T10:00:00Z",
|
||||
"end_time": "2026-01-16T12:00:00Z",
|
||||
"duration_hours": 2.0,
|
||||
"hourly_rate": 150.00,
|
||||
"total_amount": 300.00
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Store Encrypted Credential
|
||||
|
||||
```python
|
||||
POST /api/credentials
|
||||
{
|
||||
"credential_type": "api_key",
|
||||
"service_name": "OpenAI API",
|
||||
"username": "api_key",
|
||||
"password": "sk-1234567890", # Auto-encrypted
|
||||
"client_id": "client-uuid",
|
||||
"notes": "Production API key"
|
||||
}
|
||||
# Password automatically encrypted with AES-256-GCM
|
||||
# Audit log automatically created
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Important Files
|
||||
|
||||
**Session State:** `SESSION_STATE.md` - Complete project history and status
|
||||
|
||||
**Credentials:** `credentials.md` - ALL infrastructure credentials and connection details (UNREDACTED for context recovery)
|
||||
|
||||
**Session Logs:** `session-logs/YYYY-MM-DD-session.md` - Comprehensive session documentation with credentials, decisions, and infrastructure changes
|
||||
|
||||
**Documentation:**
|
||||
- `AUTOCODER_INTEGRATION.md` - AutoCoder resources guide
|
||||
- `TEST_PHASE5_RESULTS.md` - Phase 5 test results
|
||||
|
||||
**Configuration:**
|
||||
- `.env` - Environment variables (gitignored)
|
||||
- `.env.example` - Template with placeholders
|
||||
|
||||
**Tests:**
|
||||
- `test_api_endpoints.py` - Phase 4 tests
|
||||
- `test_phase5_api_endpoints.py` - Phase 5 tests
|
||||
|
||||
**AutoCoder Resources:**
|
||||
- `.claude/commands/create-spec.md` - Create app specification
|
||||
- `.claude/commands/checkpoint.md` - Create development checkpoint
|
||||
- `.claude/skills/frontend-design/` - Frontend design skill
|
||||
- `.claude/templates/` - Prompt templates (4 templates)
|
||||
- `mcp-servers/feature-management/` - Feature tracking MCP server
|
||||
|
||||
---
|
||||
|
||||
## Recent Work (from SESSION_STATE.md)
|
||||
|
||||
**Last Session:** 2026-01-18
|
||||
**Phases Completed:** 0-5 (complete)
|
||||
|
||||
**Phase 5 - Completed:**
|
||||
- MSP Work Tracking system
|
||||
- Infrastructure management endpoints
|
||||
- Encrypted credential storage
|
||||
- Security incident tracking
|
||||
|
||||
**Current State:**
|
||||
- 95+ endpoints operational
|
||||
- All migrations applied (38 tables)
|
||||
- Full test coverage
|
||||
|
||||
---
|
||||
|
||||
## Security
|
||||
|
||||
**Authentication:** JWT tokens (Argon2 password hashing)
|
||||
**Encryption:** AES-256-GCM (Fernet) for credentials
|
||||
**Audit Logging:** All credential operations logged
|
||||
|
||||
**Get JWT Token:**
|
||||
```bash
|
||||
POST /api/auth/token
|
||||
{
|
||||
"email": "user@example.com",
|
||||
"password": "your-password"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**API won't start:**
|
||||
```bash
|
||||
# Check if port 8000 is in use
|
||||
netstat -ano | findstr :8000
|
||||
|
||||
# Check database connection
|
||||
python test_db_connection.py
|
||||
```
|
||||
|
||||
**Database migration issues:**
|
||||
```bash
|
||||
# Check current revision
|
||||
alembic current
|
||||
|
||||
# Show migration history
|
||||
alembic history
|
||||
|
||||
# Upgrade to latest
|
||||
alembic upgrade head
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MCP Servers
|
||||
|
||||
**Model Context Protocol servers extend Claude Code's capabilities.**
|
||||
|
||||
**Configured Servers:**
|
||||
- **GitHub MCP** - Repository and PR management (requires token)
|
||||
- **Filesystem MCP** - Enhanced file operations (D:\ClaudeTools access)
|
||||
- **Sequential Thinking MCP** - Structured problem-solving
|
||||
|
||||
**Configuration:** `.mcp.json` (project-scoped)
|
||||
**Documentation:** `MCP_SERVERS.md` - Complete setup and usage guide
|
||||
**Setup Script:** `bash scripts/setup-mcp-servers.sh`
|
||||
|
||||
**Quick Start:**
|
||||
1. Add GitHub token to `.mcp.json` (optional)
|
||||
2. Restart Claude Code completely
|
||||
3. Test: "Use sequential thinking to analyze X"
|
||||
4. Test: "List Python files in the api directory"
|
||||
|
||||
**Note:** GitHub MCP is for GitHub.com - Gitea integration requires custom solution (see MCP_SERVERS.md)
|
||||
|
||||
---
|
||||
|
||||
## Next Steps (Optional Phase 7)
|
||||
|
||||
**Remaining entities (from original spec):**
|
||||
- File Changes API - Track file modifications
|
||||
- Command Runs API - Command execution history
|
||||
- Problem Solutions API - Knowledge base
|
||||
- Failure Patterns API - Error pattern recognition
|
||||
- Environmental Insights API - Contextual learning
|
||||
|
||||
**These are optional** - the system is fully functional without them.
|
||||
|
||||
---
|
||||
|
||||
## Coding Guidelines
|
||||
|
||||
**IMPORTANT:** Follow coding standards in `.claude/CODING_GUIDELINES.md`
|
||||
|
||||
**Key Rules:**
|
||||
- NO EMOJIS - EVER (causes encoding/parsing issues)
|
||||
- Use ASCII text markers: `[OK]`, `[ERROR]`, `[WARNING]`, `[SUCCESS]`
|
||||
- Follow PEP 8 for Python, PSScriptAnalyzer for PowerShell
|
||||
- No hardcoded credentials
|
||||
- All endpoints must have docstrings
|
||||
|
||||
---
|
||||
|
||||
## Context Recovery & Session Logs
|
||||
|
||||
**CRITICAL:** Use `/context` command when user references previous work
|
||||
|
||||
### Organized File Structure (NEW - 2026-01-20)
|
||||
**All files are now organized by project and client:**
|
||||
- `projects/[project-name]/` - Project-specific work
|
||||
- `clients/[client-name]/` - Client-specific work
|
||||
- `session-logs/` - General/cross-project logs
|
||||
- **See:** `PROJECT_ORGANIZATION.md` for complete structure
|
||||
|
||||
### Session Logs (Multiple Locations)
|
||||
**Project-Specific:**
|
||||
- Dataforth DOS: `projects/dataforth-dos/session-logs/YYYY-MM-DD-session.md`
|
||||
- ClaudeTools API: `projects/claudetools-api/session-logs/YYYY-MM-DD-session.md`
|
||||
|
||||
**Client-Specific:**
|
||||
- Format: `clients/[client-name]/session-logs/YYYY-MM-DD-session.md`
|
||||
|
||||
**General/Mixed:**
|
||||
- Format: `session-logs/YYYY-MM-DD-session.md` (root)
|
||||
|
||||
**Content:** ALL credentials, infrastructure details, decisions, commands, config changes
|
||||
**Purpose:** Full context recovery when conversation is summarized or new session starts
|
||||
**Usage:** `/save` command determines correct location and creates/appends
|
||||
|
||||
### Credentials File (credentials.md)
|
||||
- **Content:** ALL infrastructure credentials (UNREDACTED)
|
||||
- **Sections:**
|
||||
- Infrastructure - SSH Access (GuruRMM, Jupiter, AD2, D2TESTNAS)
|
||||
- Services - Web Applications (Gitea, ClaudeTools API)
|
||||
- Projects - ClaudeTools (Database, API auth, encryption keys)
|
||||
- Projects - Dataforth DOS (Update workflow, key files, folder structure)
|
||||
- **Purpose:** Centralized credentials for immediate context recovery
|
||||
- **Usage:** `/context` searches this file for server access details
|
||||
|
||||
### Context Recovery Workflow
|
||||
When user references previous work:
|
||||
1. **Use `/context` command** - Searches session logs and credentials.md
|
||||
2. **Never ask user** for information already in logs/credentials
|
||||
3. **Apply found information** - Connect to servers, continue work
|
||||
4. **Report findings** - Summarize relevant credentials and previous work
|
||||
|
||||
### Example Usage
|
||||
```
|
||||
User: "Connect to the Dataforth NAS"
|
||||
Assistant: Uses /context to find D2TESTNAS credentials (192.168.0.9, admin, Paper123!@#-nas)
|
||||
Assistant: Connects using found credentials without asking user
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
**Start API:** `uvicorn api.main:app --reload`
|
||||
**API Docs:** `http://localhost:8000/api/docs` (local) or `http://172.16.3.30:8001/api/docs` (RMM)
|
||||
**Setup MCP Servers:** `bash scripts/setup-mcp-servers.sh`
|
||||
**Database:** `172.16.3.30:3306/claudetools` (RMM Server)
|
||||
**Virtual Env:** `api\venv\Scripts\activate`
|
||||
**Coding Guidelines:** `.claude/CODING_GUIDELINES.md`
|
||||
**MCP Documentation:** `MCP_SERVERS.md`
|
||||
**AutoCoder Integration:** `AUTOCODER_INTEGRATION.md`
|
||||
|
||||
**Available Commands:**
|
||||
- `/create-spec` - Create app specification
|
||||
- `/checkpoint` - Create development checkpoint
|
||||
- `/save` - Save comprehensive session log (credentials, infrastructure, decisions)
|
||||
- `/context` - Search session logs and credentials.md for previous work
|
||||
- `/sync` - Sync ClaudeTools configuration from Gitea repository
|
||||
|
||||
**Available Skills:**
|
||||
- `/frontend-design` - Modern frontend design patterns
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2026-01-19 (Integrated C: drive behavioral rules, added context recovery system)
|
||||
**Project Progress:** Phase 5 Complete
|
||||
214
.claude/commands/1password.md
Normal file
214
.claude/commands/1password.md
Normal file
@@ -0,0 +1,214 @@
|
||||
---
|
||||
name: 1password
|
||||
description: >
|
||||
Integrate 1Password secrets management into Claude Code workflows. Use when the user wants to:
|
||||
store API keys or credentials in 1Password, read secrets from 1Password into scripts or config,
|
||||
set up .env files using 1Password secret references, rotate or update credentials, manage
|
||||
developer secrets across projects, use 1Password service accounts for CI/CD, or integrate
|
||||
1Password with tools like Claude Desktop, n8n, Docker, Supabase, GitHub Actions, or Replit.
|
||||
Triggers on phrases like "store in 1Password", "read from 1Password", "op://", "secret reference",
|
||||
"manage API keys with 1Password", "1Password CLI", or any request involving the `op` command.
|
||||
---
|
||||
|
||||
# 1Password Skill
|
||||
|
||||
## ⚠️ Critical: Never Type Secrets Into Claude Code
|
||||
|
||||
**Claude Code can see everything typed in its terminal and chat.**
|
||||
|
||||
When a user needs to store a secret, ALWAYS use the Terminal launch pattern:
|
||||
1. Generate a pre-filled script with known values already set
|
||||
2. Use `launch-in-terminal.sh` to open it in Terminal.app
|
||||
3. User types secrets in that window — Claude Code cannot see it
|
||||
4. 1Password stores the secret, outputs `op://` references back to Claude
|
||||
|
||||
```bash
|
||||
# Claude generates the script, then launches it outside its own view:
|
||||
bash scripts/launch-in-terminal.sh /tmp/setup-my-service.sh "Service Name Setup"
|
||||
```
|
||||
|
||||
Never ask users to paste API keys, passwords, or tokens into:
|
||||
- The Claude Code chat
|
||||
- A Bash tool call visible in Claude Code
|
||||
- Any file Claude Code writes before it's stored in 1Password
|
||||
|
||||
---
|
||||
|
||||
## Setup Check
|
||||
|
||||
Always verify the CLI is ready before any operation:
|
||||
|
||||
```bash
|
||||
bash scripts/check_setup.sh
|
||||
```
|
||||
|
||||
If not installed: https://developer.1password.com/docs/cli/get-started/
|
||||
If not signed in: unlock the **1Password desktop app** (after Mac restart, the app must be unlocked before the CLI works)
|
||||
|
||||
---
|
||||
|
||||
## Storing Secrets: The Terminal Launch Pattern
|
||||
|
||||
When a user needs to store a new secret or credential:
|
||||
|
||||
**Step 1 — Generate the script** (Claude does this, with known values pre-filled):
|
||||
|
||||
```bash
|
||||
cat > /tmp/setup-SERVICE.sh << 'EOF'
|
||||
bash /path/to/store-mcp-credentials.sh \
|
||||
--vault Dev \
|
||||
--item "Service Name" \
|
||||
--set "url=https://known-url.com" \
|
||||
--set "env=production" \
|
||||
--secret "api_key" \
|
||||
--secret "webhook_secret"
|
||||
EOF
|
||||
```
|
||||
|
||||
**Step 2 — Launch in Terminal.app** (secrets stay out of Claude Code):
|
||||
|
||||
```bash
|
||||
bash scripts/launch-in-terminal.sh /tmp/setup-SERVICE.sh "Service Name Setup"
|
||||
```
|
||||
|
||||
**Step 3 — Update config** (Claude uses the `op://` references from the output):
|
||||
|
||||
```json
|
||||
"SERVICE_API_KEY": "op://Dev/Service Name/api_key"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Core Patterns
|
||||
|
||||
### Read a secret
|
||||
|
||||
```bash
|
||||
op read "op://VaultName/ItemTitle/field_name"
|
||||
export API_KEY=$(op read "op://Dev/Anthropic/api_key")
|
||||
```
|
||||
|
||||
### Store a new secret
|
||||
|
||||
```bash
|
||||
# Basic
|
||||
bash scripts/store_secret.sh --title "My API Key" --field api_key --value "sk-..."
|
||||
|
||||
# With vault
|
||||
bash scripts/store_secret.sh --title "My API Key" --vault Dev --field api_key --value "sk-..."
|
||||
|
||||
# From environment variable
|
||||
bash scripts/store_secret.sh --from-env ANTHROPIC_API_KEY --title "Anthropic"
|
||||
|
||||
# Generate a secure credential
|
||||
bash scripts/store_secret.sh --title "App Secret" --field secret --generate --length 32
|
||||
```
|
||||
|
||||
### Update an existing secret
|
||||
|
||||
```bash
|
||||
bash scripts/store_secret.sh --update --title "My API Key" --field api_key --value "new-value"
|
||||
# Or directly:
|
||||
op item edit "My API Key" api_key[password]=new-value
|
||||
```
|
||||
|
||||
### Generate a .env from 1Password
|
||||
|
||||
```bash
|
||||
# Interactive — lists items, choose one
|
||||
bash scripts/env_from_op.sh
|
||||
|
||||
# From a specific item (dry run preview)
|
||||
bash scripts/env_from_op.sh --item "Project Credentials" --dry-run
|
||||
|
||||
# Write .env.tpl (secret references — safe to commit)
|
||||
bash scripts/env_from_op.sh --item "Project Credentials" --output .env.tpl
|
||||
|
||||
# Write .env with resolved real values (DO NOT commit)
|
||||
bash scripts/env_from_op.sh --item "Project Credentials" --resolve --output .env
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Secret References (op://)
|
||||
|
||||
The safest pattern — store `op://` references in config files instead of real values.
|
||||
|
||||
> **Privacy note:** `op://` references reveal vault names, item names, and field names.
|
||||
> Safe to commit to **private repos**. For public repos, check that your vault/item naming
|
||||
> doesn't expose sensitive structure (client names, internal service names, etc.).
|
||||
|
||||
```
|
||||
op://VaultName/ItemTitle/field_name
|
||||
```
|
||||
|
||||
```bash
|
||||
# .env.tpl (commit this file)
|
||||
ANTHROPIC_API_KEY=op://Dev/Anthropic/api_key
|
||||
N8N_API_KEY=op://Dev/n8n/api_key
|
||||
SUPABASE_SERVICE_KEY=op://Dev/Supabase/service_key
|
||||
|
||||
# ✅ Inject at runtime — secrets stay in subprocess, never in shell history
|
||||
op run --env-file=.env.tpl -- your-command
|
||||
|
||||
# ⚠️ Avoid sourcing into current shell — unsafe if values contain $(...) or backticks
|
||||
# source <(op run --env-file=.env.tpl -- env) ← skip this pattern
|
||||
```
|
||||
|
||||
For full syntax and edge cases: [references/secret_references.md](references/secret_references.md)
|
||||
|
||||
---
|
||||
|
||||
## Integration Guides
|
||||
|
||||
Read [references/integrations.md](references/integrations.md) for patterns with:
|
||||
|
||||
- **Claude Desktop** — MCP server config using `op run`
|
||||
- **n8n** — Environment injection at startup, credential push via API
|
||||
- **Docker / Docker Compose** — `op run -- docker compose up`
|
||||
- **GitHub Actions** — `1password/load-secrets-action`
|
||||
- **Python scripts** — subprocess + 1Password SDK
|
||||
- **Supabase** — Storing and retrieving project credentials
|
||||
- **Replit** — Local dev → Replit Secrets bridge
|
||||
- **Rotation workflow** — Update in service → update in 1Password → re-inject
|
||||
|
||||
---
|
||||
|
||||
## Common CLI Commands
|
||||
|
||||
Full reference: [references/op_commands.md](references/op_commands.md)
|
||||
|
||||
```bash
|
||||
op item list # List all items
|
||||
op item list --vault Dev # Filter by vault
|
||||
op item get "Item Title" # View item details
|
||||
op item get "Item Title" --format json # JSON output
|
||||
op vault list # List vaults
|
||||
op whoami # Check auth status
|
||||
op account list # List accounts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CI/CD: Service Accounts
|
||||
|
||||
For non-interactive environments (GitHub Actions, Docker, n8n server):
|
||||
|
||||
```bash
|
||||
export OP_SERVICE_ACCOUNT_TOKEN="ops_eyJ..."
|
||||
op read "op://Dev/MyApp/api_key" # works without signin prompt
|
||||
```
|
||||
|
||||
Create service accounts: 1Password UI → Settings → Developer → Service Accounts.
|
||||
Grant vault access only to what the service needs.
|
||||
|
||||
---
|
||||
|
||||
## Security Rules
|
||||
|
||||
1. **Never hardcode secrets** — always use `op://` references or runtime injection
|
||||
2. **Commit `.env.tpl`** to private repos only — it exposes vault/item structure, not values
|
||||
3. **Never commit `.env`** (real values) — add it to `.gitignore` immediately: `echo ".env" >> .gitignore`
|
||||
4. **Use vaults to scope access** — separate vault per project or team
|
||||
5. **Rotate on exposure** — use `store_secret.sh --update` then re-inject everywhere
|
||||
6. **Service accounts for CI/CD** — never use personal account tokens in automation
|
||||
@@ -40,15 +40,6 @@ Please create a comprehensive git checkpoint with the following steps:
|
||||
- Confirm git commit succeeded by running `git log -1`
|
||||
- Report commit status to user
|
||||
|
||||
## Part 3: Refresh Directives (MANDATORY)
|
||||
|
||||
7. **Refresh directives** (MANDATORY):
|
||||
- After checkpoint completion, auto-invoke `/refresh-directives`
|
||||
- Re-read `directives.md` to prevent shortcut-taking
|
||||
- Perform self-assessment for any violations
|
||||
- Confirm commitment to agent coordination rules
|
||||
- Report directives refreshed to user
|
||||
|
||||
## Benefits of Git Checkpoint
|
||||
|
||||
**Git Checkpoint provides:**
|
||||
|
||||
@@ -1,306 +0,0 @@
|
||||
# /refresh-directives Command
|
||||
|
||||
**Purpose:** Re-read and internalize operational directives to prevent shortcut-taking and ensure proper agent coordination.
|
||||
|
||||
---
|
||||
|
||||
## When to Use
|
||||
|
||||
**Automatic triggers (I should invoke this):**
|
||||
- After conversation compaction/summarization
|
||||
- After completing a large task
|
||||
- When detecting directive violations (database queries, emoji use, etc.)
|
||||
- At start of new work session
|
||||
- After extended conversation (>100 exchanges)
|
||||
|
||||
**Manual invocation:**
|
||||
- User types: `/refresh-directives`
|
||||
- User says: "refresh your directives" or "read your rules again"
|
||||
|
||||
---
|
||||
|
||||
## What This Command Does
|
||||
|
||||
1. **Reads directives.md** - Full file from project root
|
||||
2. **Self-assessment** - Checks recent actions for violations
|
||||
3. **Commitment** - Explicitly commits to following directives
|
||||
4. **Reports to user** - Confirms directives internalized
|
||||
|
||||
---
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Step 1: Read Directives File
|
||||
```
|
||||
Read tool → D:\ClaudeTools\directives.md
|
||||
```
|
||||
|
||||
**Must read entire file** - All sections are mandatory:
|
||||
- My Identity
|
||||
- Core Operating Principle
|
||||
- What I DO / DO NOT DO
|
||||
- Agent Coordination Rules
|
||||
- Coding Standards (NO EMOJIS)
|
||||
- Enforcement Checklist
|
||||
|
||||
### Step 2: Self-Assessment
|
||||
|
||||
**Check recent conversation for violations:**
|
||||
|
||||
**Database Operations:**
|
||||
- [ ] Did I query database directly? (Violation)
|
||||
- [ ] Did I use ssh/mysql/curl to ClaudeTools API? (Violation)
|
||||
- [ ] Did I delegate to Database Agent? (Correct)
|
||||
|
||||
**Code Generation:**
|
||||
- [ ] Did I write production code myself? (Violation)
|
||||
- [ ] Did I delegate to Coding Agent? (Correct)
|
||||
|
||||
**Emoji Usage:**
|
||||
- [ ] Did I use emojis in code/output? (Violation)
|
||||
- [ ] Did I use ASCII markers [OK]/[ERROR]? (Correct)
|
||||
|
||||
**Agent Coordination:**
|
||||
- [ ] Did I execute operations directly? (Violation)
|
||||
- [ ] Did I coordinate via agents? (Correct)
|
||||
|
||||
### Step 3: Commit to Directives
|
||||
|
||||
**Explicit commitment statement:**
|
||||
|
||||
"I have read and internalized directives.md. I commit to:
|
||||
- Coordinating via agents, not executing directly
|
||||
- Using Database Agent for ALL database operations
|
||||
- Using ASCII markers, NEVER emojis
|
||||
- Preserving my context by delegating
|
||||
- Following the enforcement checklist before every action"
|
||||
|
||||
### Step 4: Report to User
|
||||
|
||||
**Format:**
|
||||
```markdown
|
||||
## Directives Refreshed
|
||||
|
||||
I've re-read and internalized my operational directives from `directives.md`.
|
||||
|
||||
**Key commitments:**
|
||||
- [OK] Coordinate via agents (not execute directly)
|
||||
- [OK] Database Agent handles ALL database operations
|
||||
- [OK] ASCII markers only (no emojis: [OK], [ERROR], [WARNING])
|
||||
- [OK] Preserve context by delegating operations >500 tokens
|
||||
- [OK] Auto-invoke frontend-design skill for UI changes
|
||||
|
||||
**Self-assessment:** [Clean / X violations detected]
|
||||
|
||||
**Status:** Ready to coordinate effectively.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Integration Points
|
||||
|
||||
### With /checkpoint Command
|
||||
|
||||
**After git commit + database save:**
|
||||
```
|
||||
1. Execute checkpoint (git + database)
|
||||
2. Verify both succeeded
|
||||
3. Auto-invoke /refresh-directives
|
||||
4. Confirm directives refreshed
|
||||
```
|
||||
|
||||
### With /save Command
|
||||
|
||||
**After creating session log:**
|
||||
```
|
||||
1. Create/append session log
|
||||
2. Commit to repository
|
||||
3. Auto-invoke /refresh-directives
|
||||
4. Confirm directives refreshed
|
||||
```
|
||||
|
||||
### With Session Start
|
||||
|
||||
**When conversation begins:**
|
||||
```
|
||||
1. If directives.md exists → Read it immediately
|
||||
2. If starting new project → Create directives.md first
|
||||
3. Confirm directives internalized before proceeding
|
||||
```
|
||||
|
||||
### After Large Tasks
|
||||
|
||||
**When completing major work:**
|
||||
- Multi-agent coordination (3+ agents)
|
||||
- Complex problem-solving with Sequential Thinking
|
||||
- Database migrations or schema changes
|
||||
- Large code refactoring
|
||||
|
||||
**Trigger:** Auto-invoke /refresh-directives
|
||||
|
||||
---
|
||||
|
||||
## Violation Detection
|
||||
|
||||
**If I detect violations during self-assessment:**
|
||||
|
||||
1. **Acknowledge violations:**
|
||||
```
|
||||
[WARNING] Detected X directive violations in recent conversation:
|
||||
- Violation 1: Direct database query at [timestamp]
|
||||
- Violation 2: Emoji usage in output at [timestamp]
|
||||
```
|
||||
|
||||
2. **Commit to correction:**
|
||||
```
|
||||
[OK] Corrective actions:
|
||||
- Will use Database Agent for all future database operations
|
||||
- Will use ASCII markers [OK]/[ERROR] instead of emojis
|
||||
```
|
||||
|
||||
3. **Reset behavior:**
|
||||
```
|
||||
[SUCCESS] Directives re-internalized. Proceeding with proper coordination.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Example Usage
|
||||
|
||||
### User-Invoked
|
||||
```
|
||||
User: /refresh-directives
|
||||
|
||||
Claude:
|
||||
[Reads directives.md]
|
||||
[Performs self-assessment]
|
||||
[Commits to directives]
|
||||
|
||||
## Directives Refreshed
|
||||
|
||||
I've re-read my operational directives.
|
||||
|
||||
**Key commitments:**
|
||||
- [OK] Coordinate via agents, not execute
|
||||
- [OK] Database Agent for ALL data operations
|
||||
- [OK] ASCII markers only (no emojis)
|
||||
- [OK] Preserve context by delegating
|
||||
|
||||
**Self-assessment:** Clean - no violations detected
|
||||
|
||||
**Status:** Ready to coordinate effectively.
|
||||
```
|
||||
|
||||
### Auto-Invoked After Checkpoint
|
||||
```
|
||||
Claude: [Completes /checkpoint command]
|
||||
Claude: [Auto-invokes /refresh-directives]
|
||||
Claude: [Reads directives.md]
|
||||
Claude: [Confirms directives internalized]
|
||||
|
||||
Checkpoint complete. Directives refreshed. Ready for next task.
|
||||
```
|
||||
|
||||
### Auto-Invoked After Conversation Compaction
|
||||
```
|
||||
System: [Conversation compacted]
|
||||
Claude: [Detects compaction occurred]
|
||||
Claude: [Auto-invokes /refresh-directives]
|
||||
Claude: [Reads directives.md]
|
||||
Claude: [Confirms ready to proceed]
|
||||
|
||||
Context compacted. Directives re-internalized. Continuing coordination.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Technical Implementation
|
||||
|
||||
### Hook Integration
|
||||
|
||||
**Create hook:** `.claude/hooks/refresh-directives`
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Hook: Refresh Directives
|
||||
# Triggers: session-start, post-checkpoint, post-compaction
|
||||
|
||||
echo "[INFO] Triggering directives refresh..."
|
||||
echo "Reading: D:/ClaudeTools/directives.md"
|
||||
echo "[OK] Directives file available for refresh"
|
||||
```
|
||||
|
||||
### Command Recognition
|
||||
|
||||
**User input patterns:**
|
||||
- `/refresh-directives`
|
||||
- `/refresh`
|
||||
- "refresh your directives"
|
||||
- "read your rules again"
|
||||
- "re-read directives"
|
||||
|
||||
**Auto-trigger patterns:**
|
||||
- After `/checkpoint` success
|
||||
- After `/save` success
|
||||
- After conversation compaction (detect via system messages)
|
||||
- Every 50 tool uses (counter-based)
|
||||
|
||||
---
|
||||
|
||||
## Benefits
|
||||
|
||||
### Prevents Shortcut-Taking
|
||||
- Reminds me not to query database directly
|
||||
- Reinforces agent coordination model
|
||||
- Stops emoji usage before it happens
|
||||
|
||||
### Context Recovery
|
||||
- Restores operational mode after compaction
|
||||
- Ensures consistency across sessions
|
||||
- Maintains coordination principles
|
||||
|
||||
### Self-Correction
|
||||
- Detects violations automatically
|
||||
- Commits to corrective behavior
|
||||
- Provides accountability
|
||||
|
||||
### User Visibility
|
||||
- User sees when directives refreshed
|
||||
- Transparency in operational changes
|
||||
- Builds trust in coordination model
|
||||
|
||||
---
|
||||
|
||||
## Enforcement
|
||||
|
||||
**Mandatory refresh points:**
|
||||
1. [OK] Session start (if directives.md exists)
|
||||
2. [OK] After conversation compaction
|
||||
3. [OK] After /checkpoint command
|
||||
4. [OK] After /save command
|
||||
5. [OK] When user requests: /refresh-directives
|
||||
6. [OK] After completing large tasks (3+ agents)
|
||||
|
||||
**Optional refresh points:**
|
||||
- Every 50 tool uses (counter-based)
|
||||
- When detecting potential violations
|
||||
- Before critical operations (migrations, deployments)
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
**This command ensures I:**
|
||||
- Never forget my role as Coordinator
|
||||
- Always delegate to appropriate agents
|
||||
- Use ASCII markers, never emojis
|
||||
- Follow enforcement checklist
|
||||
- Maintain proper agent architecture
|
||||
|
||||
**Result:** Consistent, rule-following behavior across all sessions and contexts.
|
||||
|
||||
---
|
||||
|
||||
**Created:** 2026-01-19
|
||||
**Purpose:** Enforce directives.md compliance throughout session lifecycle
|
||||
**Status:** Active - auto-invoke at trigger points
|
||||
@@ -75,12 +75,6 @@ Format credentials as:
|
||||
1. Commit with message: "Session log: [brief description of work done]"
|
||||
2. Push to gitea remote (if configured)
|
||||
3. Confirm push was successful
|
||||
4. **Refresh directives** (MANDATORY):
|
||||
- Auto-invoke `/refresh-directives`
|
||||
- Re-read `directives.md` to prevent shortcut-taking
|
||||
- Perform self-assessment for violations
|
||||
- Confirm commitment to coordination rules
|
||||
- Report directives refreshed
|
||||
|
||||
## Purpose
|
||||
|
||||
|
||||
35
.claude/commands/scc.md
Normal file
35
.claude/commands/scc.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# /scc - Save, Commit, and Push
|
||||
|
||||
Quick command to save session log, stage everything, and push to Gitea in one shot.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Save session log** - Create/update session log for today using the /save skill logic:
|
||||
- Determine correct location based on work context (project-specific or general `session-logs/`)
|
||||
- Use format `YYYY-MM-DD-session.md`
|
||||
- If file exists, append with `## Update: HH:MM` header
|
||||
- Include: summary, credentials (unredacted), infrastructure, commands, files changed, pending tasks
|
||||
|
||||
2. **Stage all changes** - Run `git add -A` to stage everything including the new session log
|
||||
|
||||
3. **Commit** - Auto-commit with message:
|
||||
```
|
||||
scc: Session save and push from [hostname] at [timestamp]
|
||||
|
||||
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
||||
```
|
||||
|
||||
4. **Push to Gitea** - Run `git push origin main`
|
||||
|
||||
5. **Report** - Confirm what was saved, committed, and pushed
|
||||
|
||||
6. **Reaffirm roles** - After push, briefly restate:
|
||||
- You are a COORDINATOR, not an executor
|
||||
- Delegate: DB -> Database Agent, code -> Coding Agent, git -> Gitea Agent, tests -> Testing Agent
|
||||
- Do yourself: simple responses, reading 1-2 files, planning, decisions
|
||||
- >500 tokens of work = delegate. Code or database = ALWAYS delegate.
|
||||
- NO EMOJIS. Use ASCII markers: `[OK]`, `[ERROR]`, `[WARNING]`, `[SUCCESS]`, `[INFO]`
|
||||
|
||||
## Important
|
||||
- This is a FAST command - no lengthy analysis, just save and ship
|
||||
- Just save, commit, push, reaffirm, report
|
||||
@@ -1,470 +1,29 @@
|
||||
# /sync - Bidirectional ClaudeTools Sync
|
||||
|
||||
Synchronize ClaudeTools configuration, session data, and context bidirectionally with Gitea. Ensures all machines stay perfectly in sync for seamless cross-machine workflow.
|
||||
Run the automated sync script:
|
||||
|
||||
---
|
||||
```bash
|
||||
bash .claude/scripts/sync.sh
|
||||
```
|
||||
|
||||
## What Gets Synced
|
||||
The script automatically:
|
||||
1. Stages and commits local changes (if any)
|
||||
2. Fetches and pulls remote changes
|
||||
3. Pushes local changes
|
||||
4. Reports sync status
|
||||
|
||||
**FROM Local TO Gitea (PUSH):**
|
||||
- Session logs: `session-logs/*.md`
|
||||
- Project session logs: `projects/*/session-logs/*.md`
|
||||
- Credentials: `credentials.md` (private repo - safe to sync)
|
||||
- Project state: `SESSION_STATE.md`
|
||||
- Commands: `.claude/commands/*.md`
|
||||
- Directives: `directives.md`
|
||||
- File placement guide: `.claude/FILE_PLACEMENT_GUIDE.md`
|
||||
- Behavioral guidelines:
|
||||
- `.claude/CODING_GUIDELINES.md` (NO EMOJIS, ASCII markers, standards)
|
||||
- `.claude/AGENT_COORDINATION_RULES.md` (delegation guidelines)
|
||||
- `.claude/agents/*.md` (agent-specific documentation)
|
||||
- `.claude/CLAUDE.md` (project context and instructions)
|
||||
- Any other `.claude/*.md` operational files
|
||||
- Any other tracked changes
|
||||
|
||||
**FROM Gitea TO Local (PULL):**
|
||||
- All of the above from other machines
|
||||
- Latest commands and configurations
|
||||
- Updated session logs from other sessions
|
||||
- Project-specific work and documentation
|
||||
|
||||
---
|
||||
|
||||
## Execution Steps
|
||||
|
||||
### Phase 1: Prepare Local Changes
|
||||
|
||||
1. **Navigate to ClaudeTools repo:**
|
||||
```bash
|
||||
cd ~/ClaudeTools # or D:\ClaudeTools on Windows
|
||||
```
|
||||
|
||||
2. **Check repository status:**
|
||||
```bash
|
||||
git status
|
||||
```
|
||||
Report number of changed/new files to user
|
||||
|
||||
3. **Stage all changes:**
|
||||
```bash
|
||||
git add -A
|
||||
```
|
||||
This includes:
|
||||
- New/modified session logs
|
||||
- Updated credentials.md
|
||||
- SESSION_STATE.md changes
|
||||
- Command updates
|
||||
- Directive changes
|
||||
- Behavioral guidelines (CODING_GUIDELINES.md, AGENT_COORDINATION_RULES.md, etc.)
|
||||
- Agent documentation
|
||||
- Project documentation
|
||||
|
||||
4. **Auto-commit local changes with timestamp:**
|
||||
```bash
|
||||
git commit -m "sync: Auto-sync from [machine-name] at [timestamp]
|
||||
|
||||
Synced files:
|
||||
- Session logs updated
|
||||
- Latest context and credentials
|
||||
- Command/directive updates
|
||||
|
||||
Machine: [hostname]
|
||||
Timestamp: [YYYY-MM-DD HH:MM:SS]
|
||||
|
||||
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"
|
||||
```
|
||||
|
||||
**Note:** Only commit if there are changes. If working tree is clean, skip to Phase 2.
|
||||
|
||||
---
|
||||
|
||||
### Phase 2: Sync with Gitea
|
||||
|
||||
5. **Pull latest changes from Gitea:**
|
||||
```bash
|
||||
git pull origin main --rebase
|
||||
```
|
||||
|
||||
**Handle conflicts if any:**
|
||||
- Session logs: Keep both versions (rename conflicting file with timestamp)
|
||||
- credentials.md: Manual merge required - report to user
|
||||
- Other files: Use standard git conflict resolution
|
||||
|
||||
Report what was pulled from remote
|
||||
|
||||
6. **Push local changes to Gitea:**
|
||||
```bash
|
||||
git push origin main
|
||||
```
|
||||
|
||||
Confirm push succeeded
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: Apply Configuration Locally
|
||||
|
||||
7. **Copy commands to global Claude directory:**
|
||||
```bash
|
||||
mkdir -p ~/.claude/commands
|
||||
cp -r ~/ClaudeTools/.claude/commands/* ~/.claude/commands/
|
||||
```
|
||||
These slash commands are now available globally
|
||||
|
||||
8. **Apply global settings if available:**
|
||||
```bash
|
||||
if [ -f ~/ClaudeTools/.claude/settings.json ]; then
|
||||
cp ~/ClaudeTools/.claude/settings.json ~/.claude/settings.json
|
||||
fi
|
||||
```
|
||||
|
||||
9. **Sync project settings:**
|
||||
```bash
|
||||
if [ -f ~/ClaudeTools/.claude/settings.local.json ]; then
|
||||
# Read and note any project-specific settings
|
||||
fi
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Phase 4: Context Recovery
|
||||
|
||||
10. **Find and read most recent session logs:**
|
||||
|
||||
Check all locations:
|
||||
- `~/ClaudeTools/session-logs/*.md` (general)
|
||||
- `~/ClaudeTools/projects/*/session-logs/*.md` (project-specific)
|
||||
|
||||
Report the 3 most recent logs found:
|
||||
- File name and location
|
||||
- Last modified date
|
||||
- Brief summary of what was worked on (from first 5 lines)
|
||||
|
||||
11. **Read behavioral guidelines and directives:**
|
||||
```bash
|
||||
cat ~/ClaudeTools/directives.md
|
||||
cat ~/ClaudeTools/.claude/CODING_GUIDELINES.md
|
||||
cat ~/ClaudeTools/.claude/AGENT_COORDINATION_RULES.md
|
||||
```
|
||||
Internalize operational directives and behavioral rules to ensure:
|
||||
- Proper coordination mode (delegate vs execute)
|
||||
- NO EMOJIS rule enforcement
|
||||
- Agent delegation patterns
|
||||
- Coding standards compliance
|
||||
|
||||
---
|
||||
|
||||
### Phase 5: Report Sync Status
|
||||
|
||||
12. **Summarize what was synced:**
|
||||
|
||||
```
|
||||
## Sync Complete
|
||||
|
||||
[OK] Local changes pushed to Gitea:
|
||||
- X session logs updated
|
||||
- credentials.md synced
|
||||
- SESSION_STATE.md updated
|
||||
- Y command files
|
||||
|
||||
[OK] Remote changes pulled from Gitea:
|
||||
- Z files updated from other machines
|
||||
- Latest session: [most recent log]
|
||||
|
||||
[OK] Configuration applied:
|
||||
- Commands available: /checkpoint, /context, /save, /sync, etc.
|
||||
- Directives internalized (coordination mode, delegation rules)
|
||||
- Behavioral guidelines internalized (NO EMOJIS, ASCII markers, coding standards)
|
||||
- Agent coordination rules applied
|
||||
- Global settings applied
|
||||
|
||||
Recent work (last 3 sessions):
|
||||
1. [date] - [project] - [brief summary]
|
||||
2. [date] - [project] - [brief summary]
|
||||
3. [date] - [project] - [brief summary]
|
||||
|
||||
**Status:** All machines in sync. Ready to continue work.
|
||||
```
|
||||
|
||||
13. **Refresh directives (auto-invoke):**
|
||||
|
||||
Automatically invoke `/refresh-directives` to internalize all synced behavioral guidelines:
|
||||
- Re-read directives.md
|
||||
- Re-read CODING_GUIDELINES.md
|
||||
- Re-read AGENT_COORDINATION_RULES.md
|
||||
- Perform self-assessment for violations
|
||||
- Commit to following all behavioral rules
|
||||
|
||||
**Why this is critical:**
|
||||
- Ensures latest behavioral rules are active
|
||||
- Prevents shortcut-taking after sync
|
||||
- Maintains coordination discipline
|
||||
- Enforces NO EMOJIS and ASCII marker rules
|
||||
- Ensures proper agent delegation
|
||||
|
||||
---
|
||||
After the script completes, report the 3 most recent session logs:
|
||||
```bash
|
||||
ls -t session-logs/*.md projects/*/session-logs/*.md clients/*/session-logs/*.md 2>/dev/null | head -3
|
||||
```
|
||||
|
||||
## Conflict Resolution
|
||||
|
||||
### Session Log Conflicts
|
||||
If both machines created session logs with same date:
|
||||
1. Keep both versions
|
||||
2. Rename to: `YYYY-MM-DD-session-[machine].md`
|
||||
3. Report conflict to user
|
||||
|
||||
### credentials.md Conflicts
|
||||
If credentials.md has conflicts:
|
||||
1. Do NOT auto-merge
|
||||
2. Report conflict to user
|
||||
3. Show conflicting sections
|
||||
4. Ask user which version to keep or how to merge
|
||||
|
||||
### Other File Conflicts
|
||||
Standard git conflict markers:
|
||||
1. Report files with conflicts
|
||||
2. Show conflict sections
|
||||
3. Ask user to resolve manually or provide guidance
|
||||
|
||||
---
|
||||
|
||||
## Machine Detection
|
||||
|
||||
Automatically detect machine name for commit messages:
|
||||
|
||||
**Windows:**
|
||||
```powershell
|
||||
$env:COMPUTERNAME
|
||||
```
|
||||
|
||||
**Mac/Linux:**
|
||||
```bash
|
||||
hostname
|
||||
```
|
||||
|
||||
**Timestamp format:**
|
||||
```bash
|
||||
date "+%Y-%m-%d %H:%M:%S"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Benefits
|
||||
|
||||
### Seamless Multi-Machine Workflow
|
||||
- Start work on one machine, continue on another
|
||||
- All session context automatically synchronized
|
||||
- Credentials available everywhere (private repo)
|
||||
- Commands and directives stay consistent
|
||||
- Behavioral rules enforced identically (NO EMOJIS, delegation patterns, coding standards)
|
||||
|
||||
### Complete Context Preservation
|
||||
- Never lose session data
|
||||
- Full history across all machines
|
||||
- Searchable via git log
|
||||
- Rollback capability if needed
|
||||
|
||||
### Zero Manual Sync
|
||||
- One command syncs everything
|
||||
- Auto-commit prevents forgotten changes
|
||||
- Push/pull happens automatically
|
||||
- Conflicts handled gracefully
|
||||
|
||||
---
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Standard Sync (Most Common)
|
||||
```
|
||||
User: /sync
|
||||
|
||||
Claude:
|
||||
[Commits local changes]
|
||||
[Pulls from Gitea]
|
||||
[Pushes to Gitea]
|
||||
[Applies configuration]
|
||||
[Reports status]
|
||||
[Auto-invokes /refresh-directives]
|
||||
|
||||
Sync complete. 3 session logs pushed, 2 updates pulled.
|
||||
Directives refreshed. Ready to continue work.
|
||||
```
|
||||
|
||||
### Sync Before Important Work
|
||||
```
|
||||
User: "I'm switching to my other machine. /sync"
|
||||
|
||||
Claude:
|
||||
[Syncs everything]
|
||||
Report: Latest work on Dataforth DOS dashboard pushed to Gitea.
|
||||
All session logs and credentials synced.
|
||||
You can now pull on the other machine to continue.
|
||||
```
|
||||
|
||||
### Daily Morning Sync
|
||||
```
|
||||
User: /sync
|
||||
|
||||
Claude:
|
||||
[Pulls overnight changes from other machines]
|
||||
[Auto-invokes /refresh-directives]
|
||||
Report: Found 2 new sessions from yesterday evening.
|
||||
Latest: GuruRMM dashboard redesign completed.
|
||||
Context recovered. Directives refreshed. Ready for today's work.
|
||||
```
|
||||
|
||||
---
|
||||
- **Session logs:** Keep both, rename with machine suffix
|
||||
- **credentials.md:** Do NOT auto-merge, report to user
|
||||
- **Other files:** Standard git conflict resolution
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Network Issues
|
||||
If git pull/push fails:
|
||||
1. Report connection error
|
||||
2. Show what was committed locally
|
||||
3. Suggest retry or manual sync
|
||||
4. Changes are safe (committed locally)
|
||||
|
||||
### Authentication Issues
|
||||
If Gitea authentication fails:
|
||||
1. Report auth error
|
||||
2. Check SSH keys or credentials
|
||||
3. Provide troubleshooting steps
|
||||
4. Manual push may be needed
|
||||
|
||||
### Merge Conflicts
|
||||
If automatic merge fails:
|
||||
1. Report which files have conflicts
|
||||
2. Show conflict markers
|
||||
3. Ask for user guidance
|
||||
4. Offer to abort merge if needed
|
||||
|
||||
---
|
||||
|
||||
## Security Notes
|
||||
|
||||
**credentials.md Syncing:**
|
||||
- Private repository on Gitea (https://git.azcomputerguru.com)
|
||||
- Only accessible to authorized user
|
||||
- Encrypted in transit (HTTPS/SSH)
|
||||
- Safe to sync sensitive credentials
|
||||
- Enables cross-machine access
|
||||
|
||||
**What's NOT synced:**
|
||||
- `.env` files (gitignored)
|
||||
- API virtual environment (api/venv/)
|
||||
- Database files (local development)
|
||||
- Temporary files (*.tmp, *.log)
|
||||
- node_modules/ directories
|
||||
|
||||
---
|
||||
|
||||
## Integration with Other Commands
|
||||
|
||||
### After /checkpoint
|
||||
User can run `/sync` after `/checkpoint` to push the checkpoint to Gitea:
|
||||
```
|
||||
User: /checkpoint
|
||||
Claude: [Creates git commit]
|
||||
|
||||
User: /sync
|
||||
Claude: [Pushes checkpoint to Gitea]
|
||||
```
|
||||
|
||||
### Before /save
|
||||
User can sync first to see latest context:
|
||||
```
|
||||
User: /sync
|
||||
Claude: [Shows latest session logs]
|
||||
|
||||
User: /save
|
||||
Claude: [Creates session log with full context]
|
||||
```
|
||||
|
||||
### With /context
|
||||
Syncing ensures `/context` has complete history:
|
||||
```
|
||||
User: /sync
|
||||
Claude: [Syncs all session logs]
|
||||
|
||||
User: /context Dataforth
|
||||
Claude: [Searches complete session log history including other machines]
|
||||
```
|
||||
|
||||
### Auto-invokes /refresh-directives
|
||||
**IMPORTANT:** `/sync` automatically invokes `/refresh-directives` at the end:
|
||||
```
|
||||
User: /sync
|
||||
Claude:
|
||||
[Phase 1: Commits local changes]
|
||||
[Phase 2: Pulls/pushes to Gitea]
|
||||
[Phase 3: Applies configuration]
|
||||
[Phase 4: Recovers context]
|
||||
[Phase 5: Reports status]
|
||||
[Auto-invokes /refresh-directives]
|
||||
[Confirms directives internalized]
|
||||
|
||||
Sync complete. Directives refreshed. Ready to coordinate.
|
||||
```
|
||||
|
||||
**Why automatic:**
|
||||
- Ensures latest behavioral rules are active after pulling changes
|
||||
- Prevents using outdated directives from previous sync
|
||||
- Maintains coordination discipline across all machines
|
||||
- Enforces NO EMOJIS rule after any directive updates
|
||||
- Critical after conversation compaction or multi-machine sync
|
||||
|
||||
---
|
||||
|
||||
## Frequency Recommendations
|
||||
|
||||
**Daily:** Start of work day
|
||||
- Pull overnight changes
|
||||
- See what was done on other machines
|
||||
- Recover latest context
|
||||
|
||||
**After Major Work:** End of coding session
|
||||
- Push session logs
|
||||
- Share context across machines
|
||||
- Backup to Gitea
|
||||
|
||||
**Before Switching Machines:**
|
||||
- Push all local changes
|
||||
- Ensure other machine can pull
|
||||
- Seamless transition
|
||||
|
||||
**Weekly:** General maintenance
|
||||
- Keep repos in sync
|
||||
- Review session log history
|
||||
- Clean up if needed
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Already up to date" but files seem out of sync
|
||||
```bash
|
||||
# Force status check
|
||||
cd ~/ClaudeTools
|
||||
git fetch origin
|
||||
git status
|
||||
```
|
||||
|
||||
### "Divergent branches" error
|
||||
```bash
|
||||
# Rebase local changes on top of remote
|
||||
git pull origin main --rebase
|
||||
```
|
||||
|
||||
### Lost uncommitted changes
|
||||
```bash
|
||||
# Check stash
|
||||
git stash list
|
||||
|
||||
# Recover if needed
|
||||
git stash pop
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Created:** 2026-01-21
|
||||
**Purpose:** Bidirectional sync for seamless multi-machine ClaudeTools workflow
|
||||
**Repository:** https://git.azcomputerguru.com/azcomputerguru/claudetools.git
|
||||
**Status:** Active - comprehensive sync with context preservation
|
||||
If push fails with auth error, retry once (transient Gitea auth issue).
|
||||
If pull fails with conflicts, report affected files and ask for guidance.
|
||||
|
||||
396
.claude/gururmm-tunnel-plan.md
Normal file
396
.claude/gururmm-tunnel-plan.md
Normal file
@@ -0,0 +1,396 @@
|
||||
# GuruRMM Real-Time Tunnel Implementation Plan
|
||||
|
||||
## Overview
|
||||
|
||||
Transform GuruRMM agents from periodic check-in mode (30-second heartbeats) to persistent tunnel mode, enabling Claude Code on tech workstation to execute commands on remote machines through secure multiplexed channels.
|
||||
|
||||
---
|
||||
|
||||
## Architecture Summary
|
||||
|
||||
### Current State (Confirmed via exploration)
|
||||
- **Server:** Axum 0.7 @ 172.16.3.30:3001, WebSocket endpoint, AgentConnections HashMap
|
||||
- **Agent:** Tokio async, 30-second heartbeat confirmed, 3 concurrent tasks (metrics/network/heartbeat)
|
||||
- **Protocol:** Tagged JSON enums (ServerMessage/AgentMessage) with serde
|
||||
|
||||
### Key Architectural Decisions
|
||||
|
||||
1. **Tunnel Lifecycle:** Hybrid - WebSocket stays persistent, tunnel mode is operational state change
|
||||
- Agent modes: Heartbeat (default) ↔ Tunnel (active session)
|
||||
- One tunnel per agent, on-demand activation, instant mode switching
|
||||
|
||||
2. **Channel Multiplexing:** Unified protocol with channel_id routing
|
||||
- Single WebSocket, multiple logical channels
|
||||
- Enables concurrent operations (multiple terminals, simultaneous file transfers)
|
||||
- Channel types: Terminal, FileRead, FileWrite, FileList, Registry, Services
|
||||
|
||||
3. **Claude Integration:** Custom MCP server
|
||||
- Tools: `gururmm_run_command`, `gururmm_read_file`, `gururmm_write_file`, `gururmm_list_directory`, `gururmm_list_agents`
|
||||
- JWT authentication via environment variable
|
||||
- Auto-manages tunnel sessions (open on first use, keep-alive, close on idle)
|
||||
|
||||
4. **Security:** Three-layer model
|
||||
- Layer 1: JWT authentication (24h expiration)
|
||||
- Layer 2: Session authorization (tech_sessions table, 4h inactivity timeout)
|
||||
- Layer 3: Command validation (working directory allowlist, rate limiting 100/min, audit logging)
|
||||
|
||||
---
|
||||
|
||||
## Protocol Extensions
|
||||
|
||||
### New Message Types
|
||||
|
||||
```rust
|
||||
// Server → Agent
|
||||
enum ServerMessage {
|
||||
// ... existing ...
|
||||
TunnelOpen { session_id: String, tech_id: i32 },
|
||||
TunnelClose { session_id: String },
|
||||
TunnelData { channel_id: String, data: TunnelDataPayload },
|
||||
}
|
||||
|
||||
// Agent → Server
|
||||
enum AgentMessage {
|
||||
// ... existing ...
|
||||
TunnelReady { session_id: String },
|
||||
TunnelData { channel_id: String, data: TunnelDataPayload },
|
||||
TunnelError { channel_id: String, error: String },
|
||||
}
|
||||
|
||||
enum TunnelDataPayload {
|
||||
Terminal { command: String },
|
||||
TerminalOutput { stdout: String, stderr: String, exit_code: Option<i32> },
|
||||
FileRead { path: String },
|
||||
FileContent { content: Vec<u8>, mime_type: String },
|
||||
FileWrite { path: String, content: Vec<u8> },
|
||||
FileList { path: String },
|
||||
FileListResult { entries: Vec<FileEntry> },
|
||||
}
|
||||
```
|
||||
|
||||
### Agent Mode State Machine
|
||||
|
||||
```rust
|
||||
enum AgentMode {
|
||||
Heartbeat, // Default: 30s heartbeats, metrics, network monitoring
|
||||
Tunnel {
|
||||
session_id: String,
|
||||
tech_id: i32,
|
||||
channels: HashMap<String, ChannelType>,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase 1: Core Tunnel Infrastructure (Week 1)
|
||||
**Goal:** Establish tunnel mode switching and channel routing
|
||||
|
||||
**Server:**
|
||||
- Add TunnelOpen/TunnelClose/TunnelData to ServerMessage enum
|
||||
- Create tech_sessions table (id, session_id, tech_id, agent_id, opened_at, last_activity, status)
|
||||
- Implement endpoints: POST /api/v1/tunnel/open, POST /close, GET /status/:session_id
|
||||
- Add channel routing in WebSocket handler (route by channel_id)
|
||||
- Session validation middleware (JWT + ownership check)
|
||||
|
||||
**Agent:**
|
||||
- Add TunnelReady/TunnelData/TunnelError to AgentMessage enum
|
||||
- Implement AgentMode state machine
|
||||
- Add channel manager (HashMap<channel_id, ChannelHandler>)
|
||||
- Handle TunnelOpen → respond TunnelReady
|
||||
- Handle TunnelClose → cleanup channels, return to heartbeat mode
|
||||
|
||||
**Critical Files:**
|
||||
- `server/src/ws/mod.rs` - WebSocket handler, protocol definitions
|
||||
- `server/src/routes/tunnel.rs` - NEW: Tunnel API endpoints
|
||||
- `server/src/middleware/auth.rs` - Session validation
|
||||
- `agent/src/transport/websocket.rs` - WebSocket client, protocol handling
|
||||
- `agent/src/tunnel/mod.rs` - NEW: Tunnel mode manager
|
||||
- `migrations/XXX_create_tech_sessions.sql` - NEW: Database schema
|
||||
|
||||
### Phase 2: Terminal Channel (Week 2)
|
||||
**Goal:** Execute PowerShell/cmd/bash commands through tunnel
|
||||
|
||||
**Implementation:**
|
||||
- Create TerminalChannel handler on agent (spawn child process, capture streams)
|
||||
- Implement TunnelDataPayload::Terminal on server
|
||||
- Working directory validation on agent (configurable allowlist)
|
||||
- Command result streaming for long-running commands
|
||||
- Endpoint: POST /api/v1/tunnel/:session_id/command
|
||||
|
||||
**Critical Files:**
|
||||
- `agent/src/tunnel/terminal.rs` - NEW: Terminal channel handler
|
||||
- `server/src/routes/tunnel.rs` - Add command execution endpoint
|
||||
- `agent/config.toml` - Add allowed_paths configuration
|
||||
|
||||
### Phase 3: File Operations (Week 3)
|
||||
**Goal:** Read, write, list files through tunnel
|
||||
|
||||
**Implementation:**
|
||||
- Create FileChannel handler on agent
|
||||
- Chunked transfer for files > 1MB (transfer_id tracking)
|
||||
- Base64 encoding for binary data
|
||||
- MIME type detection (magic numbers)
|
||||
- Endpoints: GET /file, PUT /file, POST /file/list
|
||||
|
||||
**Critical Files:**
|
||||
- `agent/src/tunnel/file.rs` - NEW: File channel handler
|
||||
- `server/src/routes/tunnel.rs` - Add file operation endpoints
|
||||
- `common/src/transfer.rs` - NEW: Chunked transfer utilities
|
||||
|
||||
### Phase 4: MCP Server Integration (Week 4)
|
||||
**Goal:** Expose tunnel operations as MCP tools for Claude Code
|
||||
|
||||
**Implementation:**
|
||||
- Create new project: `gururmm-mcp-server` (Rust)
|
||||
- Use `mcp-server-rs` crate
|
||||
- Implement 5 core tools (run_command, read_file, write_file, list_dir, list_agents)
|
||||
- JWT token from environment variable (GURURMM_AUTH_TOKEN)
|
||||
- Auto-manage tunnel sessions (open on first tool use, 5min idle timeout)
|
||||
|
||||
**Critical Files:**
|
||||
- `mcp-server/src/main.rs` - NEW: MCP server entry point
|
||||
- `mcp-server/src/tools.rs` - NEW: Tool implementations
|
||||
- `mcp-server/src/session.rs` - NEW: Session manager
|
||||
- `mcp-server/Cargo.toml` - NEW: Dependencies
|
||||
|
||||
**MCP Config Example:**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"gururmm": {
|
||||
"command": "gururmm-mcp-server",
|
||||
"env": {
|
||||
"GURURMM_API_URL": "http://172.16.3.30:3001",
|
||||
"GURURMM_AUTH_TOKEN": "jwt-token-here"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 5: Advanced Features (Week 5+)
|
||||
- Registry operations (Windows winreg crate)
|
||||
- Service management (sc.exe/WMI on Windows, systemctl on Linux)
|
||||
- Interactive terminal with PTY (stretch goal)
|
||||
|
||||
---
|
||||
|
||||
## Database Schema
|
||||
|
||||
```sql
|
||||
CREATE TABLE tech_sessions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
session_id VARCHAR(36) UNIQUE NOT NULL,
|
||||
tech_id INTEGER NOT NULL REFERENCES techs(id),
|
||||
agent_id INTEGER NOT NULL REFERENCES agents(id),
|
||||
opened_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
last_activity TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
closed_at TIMESTAMP,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'active',
|
||||
UNIQUE(tech_id, agent_id, status) WHERE status = 'active'
|
||||
);
|
||||
|
||||
CREATE TABLE tunnel_audit (
|
||||
id SERIAL PRIMARY KEY,
|
||||
session_id VARCHAR(36) NOT NULL REFERENCES tech_sessions(session_id),
|
||||
channel_id VARCHAR(36) NOT NULL,
|
||||
operation VARCHAR(50) NOT NULL,
|
||||
details JSONB,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_tech_sessions_tech ON tech_sessions(tech_id);
|
||||
CREATE INDEX idx_tech_sessions_agent ON tech_sessions(agent_id);
|
||||
CREATE INDEX idx_tunnel_audit_session ON tunnel_audit(session_id);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API Endpoints (New)
|
||||
|
||||
```
|
||||
POST /api/v1/tunnel/open
|
||||
Body: { "agent_id": 123 }
|
||||
Response: { "session_id": "uuid", "status": "active" }
|
||||
|
||||
POST /api/v1/tunnel/close
|
||||
Body: { "session_id": "uuid" }
|
||||
|
||||
GET /api/v1/tunnel/status/:session_id
|
||||
|
||||
POST /api/v1/tunnel/:session_id/command
|
||||
Body: { "command": "...", "shell": "powershell", "working_dir": "...", "timeout": 30000 }
|
||||
|
||||
GET /api/v1/tunnel/:session_id/file?path=...
|
||||
|
||||
PUT /api/v1/tunnel/:session_id/file?path=...
|
||||
|
||||
POST /api/v1/tunnel/:session_id/file/list?path=...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MCP Tools
|
||||
|
||||
```
|
||||
gururmm_run_command(agent_id, command, shell, working_dir, timeout)
|
||||
gururmm_read_file(agent_id, path)
|
||||
gururmm_write_file(agent_id, path, content)
|
||||
gururmm_list_directory(agent_id, path)
|
||||
gururmm_list_agents()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Implementation
|
||||
|
||||
### Working Directory Validation
|
||||
```toml
|
||||
# agent/config.toml
|
||||
[security]
|
||||
allowed_paths = ["C:\\Shares", "C:\\Temp"]
|
||||
```
|
||||
|
||||
Agent validates all file operations against allowlist, rejects path traversal (`..`).
|
||||
|
||||
### Rate Limiting
|
||||
- Server enforces: 100 commands per minute per tech per agent
|
||||
- Sliding window (in-memory or Redis)
|
||||
- 429 response on limit exceeded
|
||||
- Violations logged to tunnel_audit
|
||||
|
||||
### Command Injection Prevention
|
||||
- tokio::process::Command (no shell expansion)
|
||||
- PowerShell: `-NoProfile -NonInteractive -Command`
|
||||
- Input sanitization (escape quotes, reject backticks)
|
||||
- Timeout enforcement
|
||||
|
||||
### Session Security
|
||||
- JWT 24h expiration
|
||||
- Sessions auto-expire 4h inactivity
|
||||
- One tunnel per agent (prevents concurrent session conflicts)
|
||||
- Admin force-close endpoint
|
||||
|
||||
---
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Unit Tests
|
||||
- Channel routing (correct channel receives message)
|
||||
- Session validation (JWT + ownership)
|
||||
- Command sanitization
|
||||
- Path validation (traversal prevention)
|
||||
|
||||
### Integration Tests
|
||||
- Full tunnel lifecycle (open → command → close)
|
||||
- Concurrent sessions to different agents
|
||||
- Session timeout enforcement
|
||||
- Rate limiting
|
||||
|
||||
### End-to-End Tests
|
||||
- Claude Code MCP integration
|
||||
- File upload via MCP, verify on agent
|
||||
- Multi-step workflow (read file → modify → write back)
|
||||
|
||||
---
|
||||
|
||||
## Rollout Plan
|
||||
|
||||
1. **Week 5:** Internal testing (2 agents: AD2, DESKTOP-0O8A1RL)
|
||||
2. **Week 6:** Beta release (3 power user techs)
|
||||
3. **Week 7:** General availability (all techs, documentation, training)
|
||||
|
||||
---
|
||||
|
||||
## Success Metrics
|
||||
|
||||
**Infrastructure (Phase 1-2):**
|
||||
- 95% tunnel open success rate
|
||||
- <500ms command response time
|
||||
- Zero session conflicts
|
||||
|
||||
**MCP Integration (Phase 3-4):**
|
||||
- 80% tech adoption within 2 weeks
|
||||
- >50 tunnel sessions/day
|
||||
- <5% command error rate
|
||||
|
||||
**Long-term:**
|
||||
- 20% reduction in RDP sessions
|
||||
- 90% tech satisfaction
|
||||
- <1% security incidents
|
||||
|
||||
---
|
||||
|
||||
## Risks and Mitigations
|
||||
|
||||
| Risk | Impact | Mitigation |
|
||||
|------|--------|------------|
|
||||
| Command injection | Critical | Input sanitization, no shell expansion, path allowlist |
|
||||
| Session hijacking | High | Short-lived JWT, session ownership validation, audit logging |
|
||||
| WebSocket instability | Medium | Auto-reconnect, session recovery |
|
||||
| Rate limiting too strict | Medium | Configurable per-tech limits, user feedback |
|
||||
|
||||
---
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. Registry operations scope (full access or specific hives only)?
|
||||
2. Interactive terminal priority (defer to Phase 6)?
|
||||
3. Multi-tech sessions for pair programming?
|
||||
4. MCP server credential manager integration (1Password)?
|
||||
5. Agent-side logging requirements (compliance)?
|
||||
|
||||
---
|
||||
|
||||
## Verification Plan
|
||||
|
||||
### Phase 1 Verification
|
||||
```bash
|
||||
# Tech opens tunnel session
|
||||
curl -X POST http://172.16.3.30:3001/api/v1/tunnel/open \
|
||||
-H "Authorization: Bearer $JWT" \
|
||||
-d '{"agent_id": 1}'
|
||||
# Response: {"session_id": "uuid", "status": "active"}
|
||||
|
||||
# Check agent logs - should show: "Tunnel mode activated for session uuid"
|
||||
# Check database: SELECT * FROM tech_sessions WHERE session_id = 'uuid';
|
||||
```
|
||||
|
||||
### Phase 2 Verification
|
||||
```bash
|
||||
# Execute command via tunnel
|
||||
curl -X POST http://172.16.3.30:3001/api/v1/tunnel/$SESSION_ID/command \
|
||||
-H "Authorization: Bearer $JWT" \
|
||||
-d '{"command": "Get-Date", "shell": "powershell"}'
|
||||
# Response: {"stdout": "Sunday, April 13, 2026...", "exit_code": 0}
|
||||
```
|
||||
|
||||
### Phase 4 Verification (MCP)
|
||||
```bash
|
||||
# Configure MCP server in Claude Code
|
||||
# Test tools appear in Claude's tool list
|
||||
# Execute: "List files in C:\Shares on agent ID 1"
|
||||
# Claude should call gururmm_list_directory tool
|
||||
# Verify output shows directory listing
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Next Steps After Approval
|
||||
|
||||
1. Create feature branch: `feature/real-time-tunnel`
|
||||
2. Phase 1 database migrations (tech_sessions, tunnel_audit tables)
|
||||
3. Update protocol enums (ServerMessage/AgentMessage)
|
||||
4. Implement tunnel open/close endpoints
|
||||
5. Update agent WebSocket handler for tunnel mode
|
||||
6. Unit tests for session validation
|
||||
7. Deploy to test environment
|
||||
|
||||
**Estimated Timeline:** 5 weeks to MCP integration, 7 weeks to GA
|
||||
|
||||
---
|
||||
|
||||
**Detailed plan location:** `projects/msp-tools/guru-rmm/plans/real-time-tunnel-architecture.md`
|
||||
375
.claude/machines/LINUX_PC_ONBOARDING.md
Normal file
375
.claude/machines/LINUX_PC_ONBOARDING.md
Normal file
@@ -0,0 +1,375 @@
|
||||
# Linux PC Onboarding Guide for Claude Code
|
||||
|
||||
**Purpose:** This document helps Claude Code understand how to operate correctly in the ClaudeTools environment after a fresh Linux install.
|
||||
|
||||
**Read this FIRST** before doing any work.
|
||||
|
||||
---
|
||||
|
||||
## TL;DR - Critical Rules
|
||||
|
||||
1. **You are a COORDINATOR, not an executor** - delegate significant work to agents
|
||||
2. **NO EMOJIS** - Use `[OK]`, `[ERROR]`, `[WARNING]`, `[SUCCESS]`, `[INFO]`
|
||||
3. **Never query databases directly** - Use Database Agent
|
||||
4. **Never write production code yourself** - Use Coding Agent
|
||||
5. **Always run `/sync` first** to get latest context from Gitea
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Initial Setup
|
||||
|
||||
### Run These Commands First
|
||||
|
||||
```bash
|
||||
# 1. Navigate to ClaudeTools
|
||||
cd ~/ClaudeTools # or wherever you cloned it
|
||||
|
||||
# 2. Pull latest from Gitea
|
||||
git pull origin main
|
||||
|
||||
# 3. Check GrepAI status (semantic code search)
|
||||
grepai status
|
||||
|
||||
# 4. If GrepAI watcher isn't running:
|
||||
grepai watch --background
|
||||
|
||||
# 5. Check Ollama is running (local AI)
|
||||
curl -s http://localhost:11434/api/tags | jq '.models[].name'
|
||||
```
|
||||
|
||||
### Required Models for Ollama
|
||||
|
||||
Pull these if not present:
|
||||
```bash
|
||||
ollama pull qwen3:14b # General tasks
|
||||
ollama pull codestral:22b # Code tasks
|
||||
ollama pull nomic-embed-text # Embeddings for GrepAI
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Understand Your Identity
|
||||
|
||||
### You Are a Coordinator
|
||||
|
||||
You preserve your context window by delegating work. You do NOT:
|
||||
- Query databases directly (no SSH/mysql/curl to API)
|
||||
- Write production code yourself
|
||||
- Run tests yourself
|
||||
- Commit/push yourself
|
||||
|
||||
You DO:
|
||||
- Plan and make decisions
|
||||
- Read 1-2 files for quick answers
|
||||
- Present results to the user
|
||||
- Coordinate specialized agents
|
||||
|
||||
### Delegation Rules
|
||||
|
||||
| Task | Delegate To |
|
||||
|------|-------------|
|
||||
| Database queries/inserts/updates | Database Agent |
|
||||
| Production code generation | Coding Agent |
|
||||
| Code review (MANDATORY after changes) | Code Review Agent |
|
||||
| Test execution | Testing Agent |
|
||||
| Git commits/push/branch | Gitea Agent |
|
||||
| Backups/restore | Backup Agent |
|
||||
| File exploration (broad) | Explore Agent |
|
||||
| Semantic code search | deep-explore Agent |
|
||||
| Complex reasoning | General-purpose + Sequential Thinking |
|
||||
|
||||
**Rule of thumb:** If work exceeds 500 tokens = delegate. If it touches code or database = ALWAYS delegate.
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Key Infrastructure
|
||||
|
||||
### Database
|
||||
- **Host:** 172.16.3.30:3306
|
||||
- **Database:** claudetools
|
||||
- **User:** claudetools
|
||||
- **Password:** CT_e8fcd5a3952030a79ed6debae6c954ed
|
||||
- **DO NOT** connect directly - use Database Agent
|
||||
|
||||
### API
|
||||
- **URL:** http://172.16.3.30:8001
|
||||
- **Docs:** http://172.16.3.30:8001/api/docs
|
||||
- **Auth:** JWT Bearer Token
|
||||
|
||||
### Gitea
|
||||
- **URL:** https://git.azcomputerguru.com
|
||||
- **Repo:** azcomputerguru/claudetools
|
||||
|
||||
---
|
||||
|
||||
## Step 4: Available Commands
|
||||
|
||||
These are slash commands you can invoke:
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `/sync` | Sync with Gitea, pull latest, push local changes |
|
||||
| `/checkpoint` | Git commit + database context snapshot |
|
||||
| `/save` | Create comprehensive session log |
|
||||
| `/context` | Search session logs and credentials for previous work |
|
||||
| `/refresh-directives` | Re-read behavioral rules (do after sync) |
|
||||
|
||||
### First Thing Every Session
|
||||
|
||||
```
|
||||
/sync
|
||||
```
|
||||
|
||||
This pulls latest changes from other machines and pushes your local changes.
|
||||
|
||||
---
|
||||
|
||||
## Step 5: ASCII Markers (NO EMOJIS!)
|
||||
|
||||
**Never use emojis.** They cause encoding issues across platforms.
|
||||
|
||||
Use these instead:
|
||||
|
||||
| Marker | Use For |
|
||||
|--------|---------|
|
||||
| `[OK]` | Success, completed |
|
||||
| `[SUCCESS]` | Task completed successfully |
|
||||
| `[ERROR]` | Failure, problem |
|
||||
| `[WARNING]` | Caution, potential issue |
|
||||
| `[INFO]` | Informational message |
|
||||
| `[CRITICAL]` | Severe error |
|
||||
|
||||
**Bad:**
|
||||
```
|
||||
✓ Task completed!
|
||||
⚠ Warning: check config
|
||||
```
|
||||
|
||||
**Good:**
|
||||
```
|
||||
[OK] Task completed!
|
||||
[WARNING] Check config
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 6: Local AI (Ollama)
|
||||
|
||||
Ollama runs locally for tasks that don't need Claude-level reasoning.
|
||||
|
||||
### When to Use Ollama
|
||||
|
||||
**Good for:**
|
||||
- Bulk/repetitive tasks (summarizing 50 logs)
|
||||
- Boilerplate code generation
|
||||
- Data extraction/classification
|
||||
- Draft content you'll review
|
||||
|
||||
**Bad for (use Claude):**
|
||||
- Architectural decisions
|
||||
- Security-sensitive code
|
||||
- Multi-step planning
|
||||
- Final production output
|
||||
|
||||
### How to Call Ollama
|
||||
|
||||
```bash
|
||||
# Simple prompt
|
||||
curl -s http://localhost:11434/api/generate \
|
||||
-d '{"model":"qwen3:14b","prompt":"Summarize: ...","stream":false}' \
|
||||
| jq -r '.response'
|
||||
|
||||
# Code tasks
|
||||
curl -s http://localhost:11434/api/chat \
|
||||
-d '{"model":"codestral:22b","messages":[{"role":"user","content":"..."}],"stream":false}' \
|
||||
| jq -r '.message.content'
|
||||
```
|
||||
|
||||
### Review Policy for Ollama Output
|
||||
|
||||
| Impact Level | Review Required | Examples |
|
||||
|--------------|-----------------|----------|
|
||||
| Critical | ALWAYS verify against source | Auth, security, encryption, DB migrations |
|
||||
| High | Review for correctness | API logic, business rules, infra scripts |
|
||||
| Medium | Skim for obvious errors | Internal docs, session summaries, boilerplate |
|
||||
| Low | Trust without review | Classification, reformatting, placeholders |
|
||||
|
||||
---
|
||||
|
||||
## Step 7: GrepAI (Semantic Search)
|
||||
|
||||
GrepAI indexes the codebase for natural language search.
|
||||
|
||||
### When to Use GrepAI vs Grep
|
||||
|
||||
**Use GrepAI for:**
|
||||
- "How does authentication work?"
|
||||
- "Find implementations related to user sessions"
|
||||
- Exploring unfamiliar code areas
|
||||
- Context recovery from session logs
|
||||
|
||||
**Use regular Grep for:**
|
||||
- Exact text matches
|
||||
- Known function/class names
|
||||
- Simple pattern matching
|
||||
|
||||
### Commands
|
||||
|
||||
```bash
|
||||
# Search
|
||||
grepai search "how does JWT auth work" --json
|
||||
|
||||
# Call graph tracing
|
||||
grepai trace callers "get_db"
|
||||
grepai trace callees "create_user"
|
||||
|
||||
# Start watcher (if not running)
|
||||
grepai watch --background
|
||||
|
||||
# Restart watcher (if results seem stale)
|
||||
grepai watch --stop && grepai watch --background
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 8: File Organization
|
||||
|
||||
### Where to Put Things
|
||||
|
||||
| Content Type | Location |
|
||||
|--------------|----------|
|
||||
| ClaudeTools API code | `api/`, `migrations/` |
|
||||
| Client work | `clients/[client-name]/` |
|
||||
| Project work | `projects/[project-name]/` |
|
||||
| Session logs | `session-logs/` or project-specific `session-logs/` |
|
||||
| Scripts | Project-specific `scripts/` folder |
|
||||
| Machine specs | `.claude/machines/` |
|
||||
|
||||
### Key Files to Know
|
||||
|
||||
- `credentials.md` - All infrastructure credentials (NEVER ask user for these)
|
||||
- `SESSION_STATE.md` - Project history
|
||||
- `.claude/CLAUDE.md` - Main behavioral rules (auto-loaded)
|
||||
- `.claude/CODING_GUIDELINES.md` - Coding standards
|
||||
- `.claude/agents/*.md` - Agent definitions
|
||||
|
||||
---
|
||||
|
||||
## Step 9: Context Recovery
|
||||
|
||||
When the user references previous work:
|
||||
|
||||
1. **Use `/context` command** to search session logs
|
||||
2. **Check `credentials.md`** for infrastructure details
|
||||
3. **Search session-logs/** for recent work
|
||||
4. **Never ask user** for info that's in these files
|
||||
|
||||
### Session Log Locations
|
||||
|
||||
```
|
||||
session-logs/ # General logs
|
||||
projects/*/session-logs/ # Project-specific
|
||||
clients/*/session-logs/ # Client-specific
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 10: Automatic Behaviors
|
||||
|
||||
These happen automatically - don't forget them:
|
||||
|
||||
1. **After UI changes** (HTML/CSS/JSX) -> Auto-invoke `/frontend-design`
|
||||
2. **Complex problems** (3+ issues, rejection loops) -> Use Sequential Thinking MCP
|
||||
3. **After code changes** -> Code Review Agent reviews (MANDATORY)
|
||||
4. **Complex tasks** (>3 steps) -> Create todo list with TodoWrite
|
||||
|
||||
---
|
||||
|
||||
## Step 11: SSH Configuration
|
||||
|
||||
On Linux, use system OpenSSH:
|
||||
|
||||
```bash
|
||||
# Standard SSH
|
||||
ssh user@host
|
||||
|
||||
# Never use paramiko or other SSH libraries when system SSH works
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Step 12: Self-Check After Setup
|
||||
|
||||
Run `/sync` and verify:
|
||||
|
||||
- [ ] Git pull successful
|
||||
- [ ] Latest session logs visible
|
||||
- [ ] GrepAI watcher running (`pgrep -f "grepai watch"`)
|
||||
- [ ] Ollama responding (`curl http://localhost:11434/api/tags`)
|
||||
- [ ] Can read credentials.md
|
||||
- [ ] Understand delegation model
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference Card
|
||||
|
||||
```
|
||||
IDENTITY: Coordinator (not executor)
|
||||
EMOJIS: NEVER (use [OK], [ERROR], etc.)
|
||||
DATABASE: Always delegate to Database Agent
|
||||
CODE: Always delegate to Coding Agent
|
||||
FIRST COMMAND: /sync
|
||||
CONTEXT: Check credentials.md and session-logs/
|
||||
LOCAL AI: Ollama for bulk tasks, review output
|
||||
SEARCH: GrepAI for intent, Grep for exact text
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Other Machines in This Environment
|
||||
|
||||
Check `.claude/machines/` for specs on:
|
||||
- `mikes-macbook-air.md` - M4 MacBook Air (this doc was created there)
|
||||
- (Add your machine spec after setup)
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### GrepAI Not Working
|
||||
```bash
|
||||
grepai watch --stop
|
||||
grepai watch --background
|
||||
```
|
||||
|
||||
### Ollama Not Responding
|
||||
```bash
|
||||
sudo systemctl status ollama
|
||||
sudo systemctl restart ollama
|
||||
```
|
||||
|
||||
### Git Push Rejected
|
||||
```bash
|
||||
git pull origin main --rebase
|
||||
git push origin main
|
||||
```
|
||||
|
||||
### Permission Issues
|
||||
```bash
|
||||
sudo chown -R $USER:$USER ~/ClaudeTools
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## First Task After Reading This
|
||||
|
||||
1. Run `/sync` to pull latest
|
||||
2. Run `/refresh-directives` to internalize rules
|
||||
3. Create your machine spec file in `.claude/machines/`
|
||||
4. You're ready to work!
|
||||
|
||||
---
|
||||
|
||||
**Created:** 2026-03-20
|
||||
**Created By:** Claude on Mikes-MacBook-Air.local
|
||||
**Purpose:** Help fresh Linux installs understand ClaudeTools behavioral expectations
|
||||
91
.claude/machines/acg-guru-5070.md
Normal file
91
.claude/machines/acg-guru-5070.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Machine: acg-guru-5070
|
||||
|
||||
**Hostname:** acg-guru-5070
|
||||
**Last Updated:** 2026-03-21
|
||||
|
||||
---
|
||||
|
||||
## Hardware Specs
|
||||
|
||||
| Spec | Value |
|
||||
|------|-------|
|
||||
| Model | Lenovo Legion Pro 7 16IAX10H (DMI: 83F5) |
|
||||
| CPU | Intel Core Ultra 9 275HX (24 cores, up to 5.4 GHz) |
|
||||
| Memory | 32 GB DDR5 |
|
||||
| GPU | NVIDIA GeForce RTX 5070 Ti Laptop GPU (12 GB VRAM) |
|
||||
| Storage 1 | 954 GB NVMe (SK Hynix) - CachyOS root, btrfs |
|
||||
| Storage 2 | 954 GB NVMe (SK Hynix) - /home, ext4 |
|
||||
|
||||
---
|
||||
|
||||
## Software
|
||||
|
||||
| Spec | Value |
|
||||
|------|-------|
|
||||
| OS | CachyOS Linux (Arch-based) |
|
||||
| Kernel | 6.19.9-1-cachyos |
|
||||
| DE | KDE Plasma 6.6.3 (Wayland) |
|
||||
| NVIDIA Driver | 595.45.04 (open kernel module) |
|
||||
| CUDA | 13.2 |
|
||||
| Python | 3.14 |
|
||||
|
||||
---
|
||||
|
||||
## Claude Code Environment
|
||||
|
||||
- **Working Directory:** /home/guru/ClaudeTools
|
||||
- **User:** guru
|
||||
- **Shell:** fish
|
||||
- **Git:** Configured for Gitea (git.azcomputerguru.com)
|
||||
|
||||
---
|
||||
|
||||
## Network
|
||||
|
||||
| Interface | Address |
|
||||
|-----------|---------|
|
||||
| WiFi (wlan0) | 10.3.36.218 |
|
||||
| Tailscale | 100.95.216.79 |
|
||||
|
||||
---
|
||||
|
||||
## Capabilities
|
||||
|
||||
- [x] Git operations
|
||||
- [x] SSH access to infrastructure
|
||||
- [x] GrepAI semantic search (watcher running)
|
||||
- [x] Ollama local AI (qwen3:14b, codestral:22b, nomic-embed-text)
|
||||
- [x] MCP servers available
|
||||
- [x] NVIDIA GPU (CUDA compute)
|
||||
- [x] Claude Code CLI
|
||||
|
||||
---
|
||||
|
||||
## Known Issues
|
||||
|
||||
### GPU Firmware Bug (RTX 5070 Ti)
|
||||
|
||||
The RTX 5070 Ti enters an error state (NVRM rpcSendMessage 0x00000062) after ~3-5 minutes of sustained GPU compute. This is a known Blackwell/RTX 50-series GSP firmware bug on Linux (NVIDIA bug #5953411). Affects all tested drivers (580.x, 590.x, 595.x).
|
||||
|
||||
**Impact:** GPU-accelerated ML workloads (Whisper transcription, etc.) cannot complete. GPU enters full ERR! state requiring hard power-off (warm reboot hangs with spinning symbol).
|
||||
|
||||
**Workarounds tried (none effective):**
|
||||
- Disable Runtime D3 power management
|
||||
- Enable persistence mode
|
||||
- Lock GPU clocks
|
||||
- Power cap reduction
|
||||
|
||||
**Status:** Waiting for NVIDIA driver fix. Heavy GPU compute delegated to Mac (M4).
|
||||
|
||||
### Custom Kernel for Audio
|
||||
|
||||
Running a custom-patched CachyOS kernel with the `nadimkobeissi/16iax10h-linux-sound-saga` patch for Awinic AW88399 smart amplifier support. Stock kernel has terrible speaker output. Patch is not upstreamed.
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- Primary development workstation
|
||||
- GPU works fine for display, light compute, Ollama inference — only fails under sustained heavy compute (Whisper, training)
|
||||
- Sudo: NOPASSWD configured for guru user
|
||||
- Old btrfs @home subvolume on nvme0n1 (from initial install before /home was moved to nvme1n1)
|
||||
69
.claude/machines/guru-beast-rog.md
Normal file
69
.claude/machines/guru-beast-rog.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# Machine: GURU-BEAST-ROG
|
||||
|
||||
**Hostname:** GURU-BEAST-ROG
|
||||
**Last Updated:** 2026-03-24
|
||||
|
||||
---
|
||||
|
||||
## Hardware Specs
|
||||
|
||||
| Spec | Value |
|
||||
|------|-------|
|
||||
| Model | ASUS Desktop (ROG) |
|
||||
| CPU | Intel Core i9-14900K (24 cores / 32 threads, up to 6.0 GHz) |
|
||||
| Memory | 128 GB DDR5 |
|
||||
| GPU | NVIDIA GeForce RTX 4090 (24 GB VRAM) |
|
||||
| Storage | 2 TB NVMe (WD_BLACK SN7100) |
|
||||
|
||||
---
|
||||
|
||||
## Software
|
||||
|
||||
| Spec | Value |
|
||||
|------|-------|
|
||||
| OS | Windows 11 Pro (26200) |
|
||||
| Python | 3.x (installed) |
|
||||
| Node.js | v24.14.0 |
|
||||
| Ollama | v0.18.2 |
|
||||
| Git | Installed (Git for Windows) |
|
||||
|
||||
---
|
||||
|
||||
## Claude Code Environment
|
||||
|
||||
- **Working Directory:** C:\Users\guru\ClaudeTools
|
||||
- **User:** guru
|
||||
- **Shell:** bash (Git for Windows)
|
||||
- **Git:** Configured for Gitea (git.azcomputerguru.com)
|
||||
|
||||
---
|
||||
|
||||
## Network
|
||||
|
||||
| Interface | Address |
|
||||
|-----------|---------|
|
||||
| Wi-Fi | 10.2.51.228 |
|
||||
| LAN (Local Area Connection) | 192.168.2.3 |
|
||||
|
||||
---
|
||||
|
||||
## Capabilities
|
||||
|
||||
- [x] Git operations
|
||||
- [x] SSH access to infrastructure
|
||||
- [x] GrepAI semantic search (watcher running)
|
||||
- [x] Ollama local AI (nomic-embed-text installed; qwen3:14b, codestral:22b pulling)
|
||||
- [x] MCP servers configured (filesystem, sequential-thinking, grepai)
|
||||
- [x] NVIDIA RTX 4090 GPU (CUDA compute)
|
||||
- [x] Claude Code CLI
|
||||
- [x] Bypass permissions mode (settings.json configured)
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- Powerhouse desktop -- best GPU and most RAM across all workstations
|
||||
- RTX 4090 does NOT have the GSP firmware bug that affects the 5070 Ti on Linux
|
||||
- OpenVPN Connect adapter present (VPN capable)
|
||||
- credentials.md present and populated
|
||||
- Settings.json has permissions.defaultMode: bypassPermissions
|
||||
54
.claude/machines/mikes-macbook-air.md
Normal file
54
.claude/machines/mikes-macbook-air.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Machine: Mike's MacBook Air
|
||||
|
||||
**Hostname:** Mikes-MacBook-Air.local
|
||||
**Last Updated:** 2026-03-20
|
||||
|
||||
---
|
||||
|
||||
## Hardware Specs
|
||||
|
||||
| Spec | Value |
|
||||
|------|-------|
|
||||
| Model | MacBook Air (Mac16,12) |
|
||||
| Model Number | MC6T4LL/A |
|
||||
| Chip | Apple M4 |
|
||||
| CPU Cores | 10 (4 Performance + 6 Efficiency) |
|
||||
| Memory | 16 GB |
|
||||
| Serial | J1607PM6LD |
|
||||
|
||||
---
|
||||
|
||||
## Software
|
||||
|
||||
| Spec | Value |
|
||||
|------|-------|
|
||||
| OS | macOS 26.3.1 (25D2128) |
|
||||
| Kernel | Darwin 25.3.0 |
|
||||
| Boot Volume | Macintosh HD |
|
||||
|
||||
---
|
||||
|
||||
## Claude Code Environment
|
||||
|
||||
- **Working Directory:** /Users/azcomputerguru/ClaudeTools
|
||||
- **User:** azcomputerguru
|
||||
- **Shell:** zsh
|
||||
- **Git:** Configured for Gitea (git.azcomputerguru.com)
|
||||
|
||||
---
|
||||
|
||||
## Capabilities
|
||||
|
||||
- [x] Git operations
|
||||
- [x] SSH access to infrastructure
|
||||
- [x] GrepAI semantic search (watcher running)
|
||||
- [x] Ollama local AI (qwen3:14b, codestral:22b, nomic-embed-text)
|
||||
- [x] MCP servers available
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- Primary mobile development machine
|
||||
- M4 chip provides good local AI inference performance
|
||||
- Used for radio show prep, documentation, light development
|
||||
27
.claude/memory/MEMORY.md
Normal file
27
.claude/memory/MEMORY.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Memory Index
|
||||
|
||||
## Reference
|
||||
- [Community Forum (Flarum)](reference_community_forum.md) - Flarum forum at community.azcomputerguru.com, API access, database, posting workflow
|
||||
- [Radio Show Website](reference_radio_website.md) - Astro static site at radio.azcomputerguru.com on IX server
|
||||
- [IX Server SSH Access](reference_ix_server_ssh.md) - SSH access notes, no key auth from CachyOS workstation yet
|
||||
- [IX Access via Tailscale](reference_ix_access_tailscale.md) - IX server accessible with Tailscale on, no VPN needed
|
||||
- [Neptune Access via D2TESTNAS](reference_neptune_access_d2testnas.md) - Neptune must be routed through D2TESTNAS
|
||||
- [ACG-5070 Workstation](reference_workstation_setup.md) - Windows 11, replaced CachyOS. SOPS vault, Ollama, all dev tools.
|
||||
- [Matomo Analytics](reference_matomo_analytics.md) - Self-hosted analytics at analytics.azcomputerguru.com, site IDs, tracking for all 3 sites
|
||||
- [Dataforth Contact - AJ](reference_dataforth_contact.md) - AJ at Dataforth, dataforthgit@ email forwarding to him
|
||||
- [TickTick Integration](reference_ticktick_integration.md) - OAuth API integration, MCP server, SOPS vault creds, project/task CRUD
|
||||
|
||||
## Feedback
|
||||
- [D2TESTNAS SSH Access](feedback_d2testnas_ssh.md) - Use root@192.168.0.9 with Paper123!@#, not sysadmin
|
||||
- [Bypass Permissions Setting](feedback_bypass_permissions_setting.md) - Set permissions.defaultMode to bypassPermissions in settings.json on all machines
|
||||
- [365 Remediation Tool](feedback_365_remediation_tool.md) - Always means Graph API app fabb3421, not CIPP
|
||||
|
||||
## Machine
|
||||
- [ACG-5070 Workstation Setup](reference_workstation_setup.md) - Windows 11 Pro clean install 2026-03-30, replaced CachyOS. All tools installed.
|
||||
|
||||
## Project
|
||||
- [Audio Processor Architecture](project_audio_processor_architecture.md) - Segment-first pipeline: detect breaks before transcription for complete content capture
|
||||
- [Neptune Email Routing Issues](project_email_routing_neptune.md) - Multiple clients (devcon, Sorensen/rieussetcorp) have email not routing properly from Neptune
|
||||
- [Neptune SBR Email Routing Setup](project_neptune_sbr_email_routing.md) - Full SBR routing chain, config file locations, MailProtector integration, access methods
|
||||
- [Dataforth Test Datasheet Pipeline](project_datasheet_pipeline.md) - Full pipeline rebuilt 2026-03-27. Server-side generation replaces DFWDS/Uploader. Website upload still broken.
|
||||
- [Dataforth Security Incident](project_dataforth_incident_2026-03-27.md) - DF-JOEL2 compromised, MFA deployed, IC3 filed. CA policies enforce April 4.
|
||||
30
.claude/memory/feedback_365_remediation_tool.md
Normal file
30
.claude/memory/feedback_365_remediation_tool.md
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
name: 365 Remediation Tool Reference
|
||||
description: "365 remediation tool" always means the Claude-MSP-Access Graph API app (fabb3421-8b34-484b-bc17-e46de9703418), not CIPP
|
||||
type: feedback
|
||||
---
|
||||
|
||||
When user says "365 remediation tool" or "remediation tool", they ALWAYS mean the Claude-MSP-Access Graph API application (App ID: fabb3421-8b34-484b-bc17-e46de9703418). This is NOT CIPP.
|
||||
|
||||
**Why:** User explicitly clarified this after I incorrectly navigated to CIPP. The remediation tool is direct Graph API access using client credentials flow against customer tenants.
|
||||
|
||||
**How to apply:** Authenticate directly via Graph API using the app's client secret from SOPS vault (`msp-tools/claude-msp-access-graph-api.sops.yaml`), get tenant ID from OpenID discovery for the target domain, and query Graph API endpoints directly. No browser/UI needed.
|
||||
|
||||
### Directory Role Requirements (discovered 2026-04-01)
|
||||
|
||||
Graph API permissions alone are NOT sufficient for privileged operations. The service principal also needs Entra directory roles assigned per-tenant:
|
||||
|
||||
| Operation | Required Directory Role |
|
||||
|-----------|----------------------|
|
||||
| Password reset | User Administrator |
|
||||
| Exchange transport rules, mailbox permissions | Exchange Administrator |
|
||||
|
||||
**Roles assigned so far:**
|
||||
- Valleywide Plastering (5c53ae9f...): User Administrator
|
||||
- Dataforth (7dfa3ce8...): User Administrator, Exchange Administrator
|
||||
|
||||
**For new tenants:** After admin consent, manually assign roles via Entra portal > Roles and administrators. The app cannot self-assign directory roles.
|
||||
|
||||
### Exchange Online REST API
|
||||
|
||||
For Exchange cmdlets (Get-TransportRule, Add-MailboxPermission, etc.), use scope `https://outlook.office365.com/.default` and POST to `https://outlook.office365.com/adminapi/beta/$TENANT_ID/InvokeCommand` with `{"CmdletInput":{"CmdletName":"...", "Parameters":{...}}}`.
|
||||
23
.claude/memory/feedback_bypass_permissions_setting.md
Normal file
23
.claude/memory/feedback_bypass_permissions_setting.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: Bypass Permissions and Act Autonomously
|
||||
description: Never ask for permission or confirmation -- just execute. User is an experienced engineer who wants autonomous operation.
|
||||
type: feedback
|
||||
---
|
||||
|
||||
NEVER ask "want me to proceed?", "should I?", "which option?", or any variation. Just do it.
|
||||
|
||||
**Why:** User has explicitly and repeatedly asked not to be prompted for permissions or confirmations. Every time Claude asks instead of acting, it wastes time and frustrates the user. The user is a senior engineer who trusts Claude to make reasonable decisions and execute.
|
||||
|
||||
**How to apply:**
|
||||
- When there are multiple valid approaches and no direction has been set, it's OK to ask which path. But once a path is chosen, execute without asking.
|
||||
- When a task has clear next steps, execute them immediately. Don't pause for approval.
|
||||
- Asking about unclear requirements or missing context is fine. Asking "should I do the thing you told me to do?" is not.
|
||||
- `permissions.defaultMode` must be `"bypassPermissions"` in `~/.claude/settings.json` on all machines. Both keys needed:
|
||||
```json
|
||||
{
|
||||
"permissions": { "defaultMode": "bypassPermissions" },
|
||||
"skipDangerousModePermissionPrompt": true
|
||||
}
|
||||
```
|
||||
- This applies to tool calls, git operations, file edits, agent launches -- everything.
|
||||
- The ONLY exception: truly destructive operations on shared/production systems (dropping databases, force-pushing main). Even then, a brief "doing X" is better than "should I do X?"
|
||||
11
.claude/memory/feedback_d2testnas_ssh.md
Normal file
11
.claude/memory/feedback_d2testnas_ssh.md
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
name: D2TESTNAS SSH Access
|
||||
description: D2TESTNAS SSH is root@192.168.0.9 with Paper123!@#, not sysadmin
|
||||
type: feedback
|
||||
---
|
||||
|
||||
D2TESTNAS SSH: use `root@192.168.0.9` with password `Paper123!@#`. The `sysadmin` user does not work for SSH. CachyOS workstation (acg-guru-5070) now has an ed25519 key authorized on D2TESTNAS for root.
|
||||
|
||||
**Why:** Credentials in credentials.md listed sysadmin as SSH user, which was incorrect and caused multiple failed attempts.
|
||||
|
||||
**How to apply:** When SSHing to D2TESTNAS, always use root@192.168.0.9. The SSH key at ~/.ssh/id_ed25519 (guru@acg-guru-5070) should work without password.
|
||||
44
.claude/memory/machine_windows_guru_setup_status.md
Normal file
44
.claude/memory/machine_windows_guru_setup_status.md
Normal file
@@ -0,0 +1,44 @@
|
||||
---
|
||||
name: Windows GURU-BEAST-ROG Setup Status
|
||||
description: Windows workstation setup completion status - Ollama, GrepAI, MCP, Node.js all configured
|
||||
type: reference
|
||||
---
|
||||
|
||||
# Windows Machine Setup Status (GURU-BEAST-ROG)
|
||||
|
||||
**Created:** 2026-03-23
|
||||
**Updated:** 2026-03-24
|
||||
**Machine:** GURU-BEAST-ROG (Windows 11 Pro, i9-14900K, 128GB DDR5, RTX 4090)
|
||||
|
||||
## Software Status
|
||||
|
||||
| Software | Version | Path | Status |
|
||||
|----------|---------|------|--------|
|
||||
| Python | 3.12.10 | system PATH | [OK] |
|
||||
| Git | 2.52.0.windows.1 | system PATH | [OK] |
|
||||
| Windows OpenSSH | system | C:\Windows\System32\OpenSSH\ssh.exe | [OK] |
|
||||
| Node.js | v24.14.0 | C:\Program Files\nodejs | [OK] |
|
||||
| Ollama | v0.18.2 | C:\Users\guru\AppData\Local\Programs\Ollama\ollama.exe | [OK] |
|
||||
| GrepAI | v0.35.0 | C:\Users\guru\ClaudeTools\grepai.exe | [OK] |
|
||||
| credentials.md | -- | repo root | [OK] |
|
||||
|
||||
## Ollama Models
|
||||
|
||||
| Model | Size | Status |
|
||||
|-------|------|--------|
|
||||
| nomic-embed-text | 274 MB | [OK] |
|
||||
| qwen3:14b | 9.3 GB | [OK] |
|
||||
| codestral:22b | ~12 GB | [PENDING] - download interrupted, not pulled |
|
||||
|
||||
## Configuration
|
||||
|
||||
- **.mcp.json:** filesystem, sequential-thinking, grepai servers configured
|
||||
- **GrepAI:** Initialized, watcher configured, Ollama backend with nomic-embed-text
|
||||
- **Bypass permissions:** `permissions.defaultMode: "bypassPermissions"` in ~/.claude/settings.json
|
||||
- **In-repo memory:** .claude/memory/ (syncs via Gitea)
|
||||
|
||||
## Notes
|
||||
|
||||
- Ollama not in Git Bash PATH -- use full path or open new terminal
|
||||
- GrepAI watcher may need restart after reboot: `./grepai.exe watch --background`
|
||||
- Machine registered at `.claude/machines/guru-beast-rog.md`
|
||||
32
.claude/memory/project_audio_processor_architecture.md
Normal file
32
.claude/memory/project_audio_processor_architecture.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: Audio Processor - Segment-First Architecture
|
||||
description: Revised pipeline architecture - detect breaks and split into segments BEFORE transcription for complete content capture
|
||||
type: project
|
||||
---
|
||||
|
||||
## Revised Pipeline Architecture (decided 2026-03-22)
|
||||
|
||||
Shows are almost always 4 segments per hour (8 total for a 2-hour show). Extra breaks are rare.
|
||||
|
||||
**Old approach:** Transcribe full episode -> truncate to fit LLM context -> analyze (loses content)
|
||||
|
||||
**New approach:** Detect breaks first (audio-only) -> split into ~8 segments -> transcribe each -> analyze each with full context -> cross-segment synthesis
|
||||
|
||||
### Pipeline Order
|
||||
|
||||
1. **Audio-level break detection** (no transcript needed) — loudness/compression jumps, silence gaps, known bumper fingerprints, HR1/HR2 boundary
|
||||
2. **Split into segments** — ~7-15 min each, complete audio chunks
|
||||
3. **Transcribe each segment** — smaller files, complete content, no truncation
|
||||
4. **Analyze each segment** — full transcript fits in LLM context window easily
|
||||
5. **Cross-segment synthesis** — detect topics spanning segments, callbacks ("going back to what we said before the break"), narrative arc
|
||||
6. **Generate content** — blog posts, forum posts, episode summary from complete analysis
|
||||
|
||||
### Key Insights
|
||||
|
||||
- 4 segments/hour is a strong structural prior for break detection — if 12-18 min into a segment and audio signatures appear, almost certainly a break. At 5 min, probably not.
|
||||
- Each segment transcript is ~5-10K chars — fits in any LLM context with room for detailed prompts
|
||||
- Cross-segment synthesis pass is new and essential for catching callbacks and recurring topics
|
||||
|
||||
**Why:** Solves the context window truncation problem that loses show content. Each segment gets complete analysis.
|
||||
|
||||
**How to apply:** This is the architecture direction for all future audio processor work. The existing Stage 3 segment detector needs to work without transcript input (audio-only signals). Stage 6 analyzer needs per-segment + synthesis passes.
|
||||
37
.claude/memory/project_dataforth_incident_2026-03-27.md
Normal file
37
.claude/memory/project_dataforth_incident_2026-03-27.md
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
name: Dataforth Security Incident 2026-03-27
|
||||
description: DF-JOEL2 compromised via ScreenConnect social engineering. MFA deployed. IC3 filed. C2 IPs blocked. Full remediation completed.
|
||||
type: project
|
||||
---
|
||||
|
||||
## Incident
|
||||
Joel Lohr's workstation (DF-JOEL2, 192.168.0.143) compromised via phishing email to personal Yahoo account. Attacker "Angel Raya" deployed ScreenConnect C2 backdoors. M365 account also compromised from Turkey/UK/Germany.
|
||||
|
||||
## Attacker
|
||||
- C2: 80.76.49.18 and 45.88.91.99 (AS399486, Virtuo, Montreal QC) - SUSPENDED by host
|
||||
- Cloud relay: instance-wlb9ga-relay.screenconnect.com
|
||||
- ConnectWise case: 03464184
|
||||
- IC3 complaint: 1c32ade367084be9acd548f23705736f
|
||||
|
||||
## Remediation
|
||||
- C2 IPs blocked at UDM firewall (iptables - need permanent rules in UniFi UI)
|
||||
- 3 rogue ScreenConnect clients uninstalled
|
||||
- jlohr AD password reset, M365 sessions revoked
|
||||
- 32 machines scanned clean, 28 unreachable (offline)
|
||||
- No lateral movement detected
|
||||
|
||||
## MFA Rollout
|
||||
- 3 CA policies deployed (report-only until April 4, 2026):
|
||||
- Require MFA (skip from office IP 67.206.163.122)
|
||||
- Block foreign sign-ins (US only, MFA-Travel-Bypass group for exceptions)
|
||||
- Block legacy auth
|
||||
- 19/38 users MFA-ready, 19 need to register
|
||||
- MFA notice sent to all users, deadline April 4
|
||||
|
||||
## Joel Lohr
|
||||
- Retiring March 31, 2026
|
||||
- Auto-reply directs contacts to Dan Center (dcenter@dataforth.com)
|
||||
- Account should be disabled after retirement
|
||||
|
||||
**Why:** Active security incident requiring immediate response.
|
||||
**How to apply:** Monitor CA policies in report-only mode, enforce April 4. Check 28 offline machines when available. Add C2 IPs to permanent UDM block list.
|
||||
73
.claude/memory/project_datasheet_pipeline.md
Normal file
73
.claude/memory/project_datasheet_pipeline.md
Normal file
@@ -0,0 +1,73 @@
|
||||
---
|
||||
name: Dataforth Test Datasheet Pipeline - Rebuilt 2026-03-27
|
||||
description: Full pipeline from DOS test stations to website. New server-side generation replaces DFWDS/Uploader. 72/73 Quatronix datasheets generated. AD2 crypto wipe recovery.
|
||||
type: project
|
||||
---
|
||||
|
||||
## Background
|
||||
AD2 (192.168.0.6) was wiped in a crypto/ransomware attack months ago. The test datasheet pipeline was broken. Customer Quatronix (China) blocking shipment of 328 modules (whittled to 54) without datasheets.
|
||||
|
||||
## Pipeline (5 stages, rebuilt 2026-03-27)
|
||||
|
||||
### Stage 1: DOS Test Stations (64 stations)
|
||||
- QuickBASIC programs generate test data -> C:\STAGE on each DOS PC
|
||||
- DAT files (raw test data) + TXT files (formatted datasheets)
|
||||
- CTONW.BAT copies DAT files to NAS (working)
|
||||
- CTONWTXT.BAT copies TXT files (NOT called in current AUTOEXEC v4.1 since 2026-03-12)
|
||||
- TXT files piling up in C:\STAGE since Sept 2025
|
||||
|
||||
### Stage 2: NAS <-> AD2 Sync
|
||||
- Script: C:\Shares\test\scripts\Sync-FromNAS-rsync.ps1 (every 15 min, WORKING)
|
||||
- Rsync daemon on NAS: port 873, module "test", user rsync / IQ203s32119
|
||||
- PULL: DAT files from NAS -> AD2, triggers database import
|
||||
- PUSH: Software updates from AD2 -> NAS for DOS machines
|
||||
|
||||
### Stage 3: TestDataDB (Node.js/SQLite, WORKING)
|
||||
- App: C:\Shares\testdatadb\ (Windows service "testdatadb", auto-start)
|
||||
- API: http://192.168.0.6:3000
|
||||
- Database: C:\Shares\testdatadb\database\testdata.db (2.27M records)
|
||||
- Import: database/import.js (post-import hook calls export)
|
||||
- **NEW: Spec parser** (parsers/spec-reader.js) - reads binary spec DATs, 1470 models
|
||||
- **NEW: Exact-match formatter** (templates/datasheet-exact.js) - reverse-engineered from QB
|
||||
- **NEW: Auto-export** (database/export-datasheets.js) - generates TXT to X:\For_Web
|
||||
|
||||
### Stage 4: WebShare (X: = \\ad2\webshare = C:\Shares\webshare)
|
||||
- X:\Test_Datasheets - incoming (staging for old DFWDS)
|
||||
- X:\For_Web - validated datasheets (501K+ files, pre-2026 archived to year subfolders)
|
||||
- X:\For_Web_PDF - PDF versions (4.7K files)
|
||||
- X:\Bad_Datasheets - invalid files (18K)
|
||||
- X:\Datasheets_Log - DFWDS logs
|
||||
|
||||
### Stage 5: Website Upload (BROKEN)
|
||||
- Old endpoints: dataforth.com/Services/{Uploader,DirectoryManifest,DeleteFile}.aspx - ALL 404
|
||||
- Credentials: DataforthWebShare / Data6277
|
||||
- TestDataSheetUploader (VB.NET, Hoffman) - not running, config pointed to dev paths
|
||||
- Legacy site: legacy.dataforth.com/TestDataReport_Print.aspx (still works, no auth)
|
||||
- New site: dataforth.com/TestDataReport (requires OIDC login)
|
||||
|
||||
## What Was Eliminated by Rebuild
|
||||
- CTONWTXT.BAT (DOS TXT transfer) - no longer needed, server generates from DAT data
|
||||
- DFWDS.exe (VB6 filename decoder) - no longer needed
|
||||
- TestDataSheetUploader (VB.NET web uploader) - endpoints dead anyway
|
||||
|
||||
## Key File Encoding
|
||||
H-prefix decode: A=10, B=11, C=12, D=13, E=14, F=15, G=16, H=17, I=18, J=19
|
||||
Example: H8601-6.TXT -> serial 178601-6
|
||||
New pipeline extracts SN from DAT record data directly, not filenames.
|
||||
|
||||
## Open Items
|
||||
1. Website upload replacement (old ASP.NET endpoints dead)
|
||||
2. 7B datasheet formatting (specs loaded, needs 7B-specific layout, ~830K records)
|
||||
3. SCM5B49 spec file empty - need from John Lehman
|
||||
4. Service permissions (runs as SYSTEM, causes SHM/WAL conflicts)
|
||||
5. New product lines: MAQ20/PWRM (XLS), 10D (JSON, ~May 2026), DSCMHV
|
||||
|
||||
## Key Contacts
|
||||
- John Lehman (jlehman@dataforth.com) - Engineering, QB code, specs
|
||||
- Peter Iliya (pIliya@dataforth.com) - Applications Engineer, manual datasheet retrieval
|
||||
- Ken Hoffman - TestDataSheetUploader author (VB.NET), DFWDS author, unresponsive
|
||||
- Georg Haubner (ghaubner@dataforth.com) - D: drive has pre-crypto backup of network shares
|
||||
- Ginger (gy@quatronix-cn.com) - Quatronix China, customer requesting datasheets
|
||||
|
||||
**Why:** Critical business issue - customer refusing shipments without datasheets.
|
||||
**How to apply:** Pipeline is mostly rebuilt. Priority: website upload replacement, then 7B support.
|
||||
11
.claude/memory/project_email_routing_neptune.md
Normal file
11
.claude/memory/project_email_routing_neptune.md
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
name: Neptune Email Routing Issues
|
||||
description: Multiple clients (devcon, Sorensen/rieussetcorp) have email not routing properly from Neptune
|
||||
type: project
|
||||
---
|
||||
|
||||
Sorensen (rieussetcorp) and devcon both have the same email routing issue from Neptune — emails not routing properly.
|
||||
|
||||
**Why:** Recurring issue affecting multiple clients, likely a shared configuration or Neptune platform problem rather than isolated incidents.
|
||||
|
||||
**How to apply:** When troubleshooting email routing for any client on Neptune, check if the fix applied to one client needs to be replicated for others. Track as a systemic Neptune issue, not individual client problems.
|
||||
49
.claude/memory/project_neptune_sbr_email_routing.md
Normal file
49
.claude/memory/project_neptune_sbr_email_routing.md
Normal file
@@ -0,0 +1,49 @@
|
||||
---
|
||||
name: Neptune SBR Email Routing Setup
|
||||
description: How outbound email routing works on Neptune Exchange - SBR agent, MailProtector smarthost, send connectors, and common fix for new clients
|
||||
type: project
|
||||
---
|
||||
|
||||
## Neptune Outbound Email Routing Chain
|
||||
|
||||
1. User sends mail from Exchange mailbox on Neptune (172.16.3.11)
|
||||
2. **Microsoft.Exchange.SBR** transport agent (Priority 12) fires on OnResolved event
|
||||
3. SBR reads config files at `C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\agents\Custom\`:
|
||||
- `Microsoft.Exchange.SBR.InternalDomains.config` — list of domains SBR handles
|
||||
- `Microsoft.Exchange.SBR.OverrideSettings.config` — maps `domain.com;domain.sbr` for routing
|
||||
- `Microsoft.Exchange.SBR.IgnoreAuthAs.config` — exclusions
|
||||
4. SBR rewrites recipient routing to `.sbr` domain (e.g., `rieussetcorp.sbr`)
|
||||
5. Exchange matches `.sbr` address space to the corresponding Send Connector (e.g., `Outbound.Sorensen`)
|
||||
6. Send connector smarthosts through MailProtector: `domain-com.outbound.emailservice.io`
|
||||
7. MailProtector relays to final destination
|
||||
|
||||
There is also a **messageconcept ExSBR** agent at Priority 11 (`C:\Program Files\messageconcept\ExSBR\`).
|
||||
|
||||
## Common Issue: New client or server move
|
||||
|
||||
When Neptune's IP changes or a new domain is added, MailProtector must have the sending server IP authorized. Without this, MailProtector accepts the relay but drops/rejects the message.
|
||||
|
||||
**Fix (2026-03-22 for rieussetcorp.com):** Added 67.206.163.124 and 67.206.163.122 to MailProtector's authorized sender IPs.
|
||||
|
||||
## Neptune Location
|
||||
|
||||
Neptune physically moved from ACG office (72.194.62.7) to Dataforth (67.206.163.124 inbound, 67.206.163.122 outbound). SNAT rule on Dataforth UDM (`/data/on_boot.d/10-neptune-snat.sh`) should force outbound to use .124.
|
||||
|
||||
## Access
|
||||
|
||||
- WinRM: `172.16.3.11`, ACG\administrator, via pywinrm with NTLM
|
||||
- Exchange PS: Connect via `New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://neptune.acg.local/PowerShell/ -Authentication Kerberos`
|
||||
- Requires Tailscale route through D2TESTNAS (192.168.0.9) for 172.16.0.0/22
|
||||
|
||||
## Known Issues (as of 2026-03-22)
|
||||
|
||||
- 67.206.163.122 has no PTR record and is blacklisted by some providers
|
||||
- SNAT rule may not be active — outbound was going as .122 not .124 on 3/16. Need to check UDM (192.168.0.254) — couldn't auth via SSH tonight, check in morning
|
||||
- MAIL transport server still exists in Exchange config but server is decommissioned
|
||||
- Spam queues with junk domains (wwwyamaha666.ru, bestspatulas.com, etc.)
|
||||
- Tailscale 172.16.0.0/22 route moved from ACG pfSense to D2TESTNAS — may need permanent solution
|
||||
- UDM SSH password (Paper123!@#-unifi) was rejected — may have changed
|
||||
|
||||
## Resolved (2026-03-22)
|
||||
|
||||
- rieussetcorp.com outbound: Added 67.206.163.124 and .122 to MailProtector authorized IPs — mail now flowing
|
||||
48
.claude/memory/reference_community_forum.md
Normal file
48
.claude/memory/reference_community_forum.md
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
name: Community Forum (Flarum)
|
||||
description: Flarum forum at community.azcomputerguru.com - platform details, API access, database credentials, and posting workflow
|
||||
type: reference
|
||||
---
|
||||
|
||||
## Community Forum - Flarum
|
||||
|
||||
- **URL:** https://community.azcomputerguru.com
|
||||
- **Platform:** Flarum 1.8.14
|
||||
- **Server:** IX server (172.16.3.10), cPanel account `azcomputerguru`
|
||||
- **Document Root:** `/home/azcomputerguru/public_html/community/public`
|
||||
- **PHP Version:** 8.1.33
|
||||
|
||||
### Database
|
||||
- **Host:** localhost (on IX server)
|
||||
- **Database:** `azcompu_flarum`
|
||||
- **User:** `azcompu_flarum`
|
||||
- **Password:** `Fl@rum2026!CGS`
|
||||
|
||||
### API
|
||||
- **API Key:** `581b6c8c162a383ba87757f41b4381e9bf8db61d71bd578ee97fe32b7aeac046` (admin user, ID 1)
|
||||
- **API Base:** `https://community.azcomputerguru.com/api`
|
||||
- **Note:** Cloudflare blocks external API access. Must either:
|
||||
1. Use `--resolve` with `curl -k` from IX server localhost
|
||||
2. Use direct PHP/database script on IX server (preferred, more reliable)
|
||||
|
||||
### Forum Tags (Categories)
|
||||
| ID | Name | Slug |
|
||||
|----|------|------|
|
||||
| 1 | General | general |
|
||||
| 2 | Tech News | tech-news |
|
||||
| 3 | Security & Privacy | security-privacy |
|
||||
| 4 | Artificial Intelligence | artificial-intelligence |
|
||||
| 5 | Space Tech | space-tech |
|
||||
| 6 | Gadgets & Hardware | gadgets-hardware |
|
||||
| 7 | How-Tos & Tips | how-tos-tips |
|
||||
| 8 | Show Discussion | show-discussion |
|
||||
| 9 | Off-Topic | off-topic |
|
||||
|
||||
### Posting Workflow
|
||||
Cloudflare blocks the Flarum REST API from external requests. To create posts programmatically:
|
||||
1. Write a PHP script that inserts directly into the database (discussions + posts + discussion_tag tables)
|
||||
2. SCP the script and JSON payload to IX server `/tmp/`
|
||||
3. Execute via `php /tmp/script.php` over SSH
|
||||
4. Clean up temp files
|
||||
|
||||
**How to apply:** Use this when the user asks to create forum posts or manage the community forum.
|
||||
7
.claude/memory/reference_dataforth_contact.md
Normal file
7
.claude/memory/reference_dataforth_contact.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
name: Dataforth Contact - AJ
|
||||
description: AJ at Dataforth - email forwarding setup needed for dataforthgit@ address
|
||||
type: reference
|
||||
---
|
||||
|
||||
AJ at Dataforth needs messages sent to the dataforthgit@ email address to forward to him.
|
||||
7
.claude/memory/reference_ix_access_tailscale.md
Normal file
7
.claude/memory/reference_ix_access_tailscale.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
name: IX Server Access via Tailscale
|
||||
description: IX server (ix.azcomputerguru.com) is accessible with Tailscale on, no VPN needed
|
||||
type: reference
|
||||
---
|
||||
|
||||
IX server (ix.azcomputerguru.com / 172.16.3.10) can be accessed directly when Tailscale is on. No separate VPN connection required.
|
||||
18
.claude/memory/reference_ix_server_ssh.md
Normal file
18
.claude/memory/reference_ix_server_ssh.md
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
name: IX Server SSH Access
|
||||
description: SSH access notes for IX server - key auth not set up on CachyOS workstation, must use sshpass with password
|
||||
type: reference
|
||||
---
|
||||
|
||||
## IX Server SSH from CachyOS Workstation
|
||||
|
||||
- **Host:** 172.16.3.10 (ix.azcomputerguru.com)
|
||||
- **User:** root
|
||||
- **Password:** See credentials.md
|
||||
- **SSH Key Auth:** NOT configured on CachyOS workstation (acg-guru-5070)
|
||||
- **Must use:** `sshpass -p 'PASSWORD' ssh -o StrictHostKeyChecking=no -o PubkeyAuthentication=no root@172.16.3.10`
|
||||
- **Suppress warnings:** Pipe through `grep -v WARNING | grep -v 'not using'` or `tail`
|
||||
|
||||
**Why:** The SSH key from this machine hasn't been added to IX server's authorized_keys yet. The old WSL key (guru@wsl) was authorized but this is a new CachyOS install.
|
||||
|
||||
**How to apply:** When running commands on IX server, use sshpass approach. Consider setting up SSH key auth to simplify future access.
|
||||
40
.claude/memory/reference_matomo_analytics.md
Normal file
40
.claude/memory/reference_matomo_analytics.md
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
name: Matomo Analytics
|
||||
description: Self-hosted Matomo analytics at analytics.azcomputerguru.com - credentials, site IDs, tracking setup for all 3 sites
|
||||
type: reference
|
||||
---
|
||||
|
||||
## Matomo Analytics
|
||||
|
||||
- **URL:** https://analytics.azcomputerguru.com
|
||||
- **Platform:** Matomo 5.8.0 (PHP)
|
||||
- **Server:** IX server (172.16.3.10), cPanel account `azcomputerguru`
|
||||
- **Document Root:** `/home/azcomputerguru/public_html/analytics/`
|
||||
|
||||
### Login
|
||||
- **User:** MikeSwanson
|
||||
- **Password:** Mat0mo2026!CGS
|
||||
- **Email:** mike@azcomputerguru.com
|
||||
|
||||
### Database
|
||||
- **Host:** localhost (on IX server)
|
||||
- **Database:** `azcompu_matomo`
|
||||
- **User:** `azcompu_matomo`
|
||||
- **Password:** `Mat0mo2026!CGS`
|
||||
|
||||
### Tracked Sites
|
||||
| Site ID | Name | URL | Tracking Method |
|
||||
|---------|------|-----|-----------------|
|
||||
| 1 | AZ Computer Guru | https://azcomputerguru.com | WordPress mu-plugin (`wp-content/mu-plugins/matomo-tracking.php`) |
|
||||
| 2 | Community Forum | https://community.azcomputerguru.com | Flarum `custom_header` DB setting |
|
||||
| 3 | Radio Show | https://radio.azcomputerguru.com | Injected into HTML files before `</head>` |
|
||||
|
||||
### Cron
|
||||
- Archiving cron runs every 5 minutes as `azcomputerguru` user
|
||||
- Command: `php /home/azcomputerguru/public_html/analytics/console core:archive`
|
||||
|
||||
### Cloudflare
|
||||
- DNS record points to 72.194.62.5, proxied (orange cloud)
|
||||
- Was previously pointing to wrong IP (52.52.94.202), fixed 2026-03-20
|
||||
|
||||
**How to apply:** Use this when managing analytics, adding new sites to track, or troubleshooting tracking code.
|
||||
7
.claude/memory/reference_neptune_access_d2testnas.md
Normal file
7
.claude/memory/reference_neptune_access_d2testnas.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
name: Neptune Access via D2TESTNAS
|
||||
description: Neptune Exchange server must be accessed by routing through D2TESTNAS (not direct VPN)
|
||||
type: reference
|
||||
---
|
||||
|
||||
Neptune (neptune.acghosting.com / 172.16.3.11) must be accessed by routing through D2TESTNAS, not via direct VPN connection.
|
||||
23
.claude/memory/reference_radio_website.md
Normal file
23
.claude/memory/reference_radio_website.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: Radio Show Website
|
||||
description: The Computer Guru Show website at radio.azcomputerguru.com - Astro static site on IX server cPanel
|
||||
type: reference
|
||||
---
|
||||
|
||||
## Radio Show Website
|
||||
|
||||
- **URL:** https://radio.azcomputerguru.com
|
||||
- **Platform:** Astro 6.0.4 (static site generator)
|
||||
- **Server:** IX server (172.16.3.10), cPanel account `azcomputerguru`
|
||||
- **Document Root:** `/home/azcomputerguru/public_html/radio`
|
||||
- **Source Code:** `projects/radio-show/website/` in ClaudeTools repo
|
||||
- **Build:** `cd projects/radio-show/website && npm run build` produces `dist/` folder
|
||||
- **Deploy:** rsync/SCP `dist/` contents to document root on IX server
|
||||
|
||||
### Community Link
|
||||
- The community page (`/community`) links to:
|
||||
- Discord server (placeholder, WidgetBot)
|
||||
- Flarum forum at https://community.azcomputerguru.com
|
||||
- Newsletter signup (placeholder)
|
||||
|
||||
**How to apply:** Use when deploying website updates or managing the radio show project.
|
||||
33
.claude/memory/reference_ticktick_integration.md
Normal file
33
.claude/memory/reference_ticktick_integration.md
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
name: TickTick Integration
|
||||
description: TickTick API integration for project/task management - OAuth credentials in SOPS vault, MCP server, API service
|
||||
type: reference
|
||||
---
|
||||
|
||||
## TickTick Integration (Built 2026-03-31)
|
||||
|
||||
**App Name:** ClaudeTools (registered at developer.ticktick.com)
|
||||
|
||||
### Credentials
|
||||
- SOPS vault: `services/ticktick.sops.yaml`
|
||||
- Fields: `credentials.client_id`, `credentials.client_secret`, `credentials.oauth_redirect_url`
|
||||
- OAuth tokens: `mcp-servers/ticktick/.tokens.json` (gitignored, auto-refreshed)
|
||||
|
||||
### Components
|
||||
- **MCP Server:** `mcp-servers/ticktick/ticktick_mcp.py` - 9 tools for Claude Code (registered in `.mcp.json`)
|
||||
- **OAuth Auth:** `mcp-servers/ticktick/ticktick_auth.py` - One-time browser auth flow (localhost:9876 callback)
|
||||
- **API Service:** `api/services/ticktick_service.py` - Async service, SOPS vault credentials, auto token refresh
|
||||
- **API Router:** `api/routers/ticktick.py` - REST at `/api/ticktick/`, JWT-protected
|
||||
|
||||
### TickTick API
|
||||
- Base URL: `https://api.ticktick.com/open/v1`
|
||||
- Auth: OAuth 2.0 Bearer tokens, scopes: `tasks:read tasks:write`
|
||||
- No webhooks (must poll), no search endpoint (filter client-side)
|
||||
- Priority values: 0=none, 1=low, 3=medium, 5=high (non-sequential)
|
||||
- Token endpoint requires `application/x-www-form-urlencoded` (not JSON)
|
||||
|
||||
### MCP Tools
|
||||
`ticktick_list_projects`, `ticktick_get_project`, `ticktick_create_project`, `ticktick_update_project`, `ticktick_delete_project`, `ticktick_create_task`, `ticktick_update_task`, `ticktick_complete_task`, `ticktick_delete_task`
|
||||
|
||||
### Re-auth
|
||||
If tokens expire completely, run: `python mcp-servers/ticktick/ticktick_auth.py` from bash (not PowerShell - needs vault access via bash).
|
||||
32
.claude/memory/reference_workstation_setup.md
Normal file
32
.claude/memory/reference_workstation_setup.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
name: ACG-5070 Workstation Setup
|
||||
description: Primary workstation ACG-5070 (Windows 11 Pro), clean install 2026-03-30. Replaced CachyOS.
|
||||
type: reference
|
||||
---
|
||||
|
||||
## Workstation: ACG-5070
|
||||
|
||||
- **OS:** Windows 11 Pro (clean install 2026-03-30)
|
||||
- **Previous OS:** CachyOS Linux (gone, replaced by Windows)
|
||||
- **Hardware:** ASUS laptop, Intel Arrow Lake-S + NVIDIA RTX 5070 Ti Mobile, dual NVMe
|
||||
|
||||
### Installed Tools
|
||||
- Node.js v24.14.1, npm 11.11.0
|
||||
- Git 2.53.0, Python 3.14.3
|
||||
- 1Password CLI 2.33.1 (desktop app integration)
|
||||
- Ollama 0.18.3 (models on D:\OllamaModels: qwen3:14b, codestral:22b, nomic-embed-text)
|
||||
- Claude Code 2.1.87
|
||||
- sops 3.7.3, age 1.3.1, yq 4.52.5
|
||||
- jq, curl, Windows OpenSSH
|
||||
- Missing: gh (GitHub CLI)
|
||||
|
||||
### SOPS Vault
|
||||
- age key: %APPDATA%\sops\age\keys.txt
|
||||
- Vault repo: D:\vault (git.azcomputerguru.com/azcomputerguru/vault)
|
||||
- 1Password backup: "age Key - ACG-5070 (Windows)" in Infrastructure vault
|
||||
|
||||
### Other Machines
|
||||
- GURU-BEAST-ROG (Windows 11) -- needs vault setup (sops, age, yq, clone repo, generate age key, rotate)
|
||||
- Mikes-MacBook-Air (macOS) -- needs vault setup
|
||||
|
||||
**How to apply:** Reference when troubleshooting workstation issues or setting up additional services.
|
||||
5
.claude/scripts/sync.bat
Normal file
5
.claude/scripts/sync.bat
Normal file
@@ -0,0 +1,5 @@
|
||||
@echo off
|
||||
REM ClaudeTools Sync - Windows Wrapper
|
||||
REM Calls the bash sync script via Git Bash
|
||||
|
||||
bash "%~dp0sync.sh"
|
||||
118
.claude/scripts/sync.sh
Executable file
118
.claude/scripts/sync.sh
Executable file
@@ -0,0 +1,118 @@
|
||||
#!/bin/bash
|
||||
# ClaudeTools Bidirectional Sync Script
|
||||
# Ensures proper pull BEFORE push on all machines
|
||||
|
||||
set -e # Exit on error
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Detect machine name
|
||||
if [ -n "$COMPUTERNAME" ]; then
|
||||
MACHINE="$COMPUTERNAME"
|
||||
else
|
||||
MACHINE=$(hostname)
|
||||
fi
|
||||
|
||||
# Timestamp
|
||||
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
|
||||
|
||||
echo -e "${GREEN}[OK]${NC} Starting ClaudeTools sync from $MACHINE at $TIMESTAMP"
|
||||
|
||||
# Navigate to ClaudeTools directory
|
||||
if [ -d "$HOME/ClaudeTools" ]; then
|
||||
cd "$HOME/ClaudeTools"
|
||||
elif [ -d "/d/ClaudeTools" ]; then
|
||||
cd "/d/ClaudeTools"
|
||||
elif [ -d "D:/ClaudeTools" ]; then
|
||||
cd "D:/ClaudeTools"
|
||||
else
|
||||
echo -e "${RED}[ERROR]${NC} ClaudeTools directory not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}[OK]${NC} Working directory: $(pwd)"
|
||||
|
||||
# Phase 1: Check and commit local changes
|
||||
echo ""
|
||||
echo "=== Phase 1: Local Changes ==="
|
||||
|
||||
if ! git diff-index --quiet HEAD -- 2>/dev/null; then
|
||||
echo -e "${YELLOW}[INFO]${NC} Local changes detected"
|
||||
|
||||
# Show status
|
||||
git status --short
|
||||
|
||||
# Stage all changes
|
||||
echo -e "${GREEN}[OK]${NC} Staging all changes..."
|
||||
git add -A
|
||||
|
||||
# Commit with timestamp
|
||||
COMMIT_MSG="sync: Auto-sync from $MACHINE at $TIMESTAMP
|
||||
|
||||
Synced files:
|
||||
- Session logs updated
|
||||
- Latest context and credentials
|
||||
- Command/directive updates
|
||||
|
||||
Machine: $MACHINE
|
||||
Timestamp: $TIMESTAMP
|
||||
|
||||
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"
|
||||
|
||||
git commit -m "$COMMIT_MSG"
|
||||
echo -e "${GREEN}[OK]${NC} Changes committed"
|
||||
else
|
||||
echo -e "${GREEN}[OK]${NC} No local changes to commit"
|
||||
fi
|
||||
|
||||
# Phase 2: Sync with remote (CRITICAL: Pull BEFORE Push)
|
||||
echo ""
|
||||
echo "=== Phase 2: Remote Sync (Pull + Push) ==="
|
||||
|
||||
# Fetch to see what's available
|
||||
echo -e "${GREEN}[OK]${NC} Fetching from remote..."
|
||||
git fetch origin
|
||||
|
||||
# Check if remote has updates
|
||||
LOCAL=$(git rev-parse main)
|
||||
REMOTE=$(git rev-parse origin/main)
|
||||
|
||||
if [ "$LOCAL" != "$REMOTE" ]; then
|
||||
echo -e "${YELLOW}[INFO]${NC} Remote has updates, pulling..."
|
||||
|
||||
# Pull with rebase
|
||||
if git pull origin main --rebase; then
|
||||
echo -e "${GREEN}[OK]${NC} Successfully pulled remote changes"
|
||||
git log --oneline "$LOCAL..origin/main"
|
||||
else
|
||||
echo -e "${RED}[ERROR]${NC} Pull failed - may have conflicts"
|
||||
echo -e "${YELLOW}[INFO]${NC} Resolve conflicts and run sync again"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo -e "${GREEN}[OK]${NC} Already up to date with remote"
|
||||
fi
|
||||
|
||||
# Push local changes
|
||||
echo ""
|
||||
echo -e "${GREEN}[OK]${NC} Pushing local changes to remote..."
|
||||
if git push origin main; then
|
||||
echo -e "${GREEN}[OK]${NC} Successfully pushed to remote"
|
||||
else
|
||||
echo -e "${RED}[ERROR]${NC} Push failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Phase 3: Report final status
|
||||
echo ""
|
||||
echo "=== Sync Complete ==="
|
||||
echo -e "${GREEN}[OK]${NC} Local branch: $(git rev-parse --abbrev-ref HEAD)"
|
||||
echo -e "${GREEN}[OK]${NC} Current commit: $(git log -1 --oneline)"
|
||||
echo -e "${GREEN}[OK]${NC} Remote status: $(git status -sb | head -1)"
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}[SUCCESS]${NC} All machines in sync. Ready to continue work."
|
||||
222
.claude/skills/1password/references/integrations.md
Normal file
222
.claude/skills/1password/references/integrations.md
Normal file
@@ -0,0 +1,222 @@
|
||||
# 1Password Integration Patterns
|
||||
|
||||
Common patterns for integrating 1Password with developer tools and AI workflows.
|
||||
|
||||
## Claude Code / Claude Desktop
|
||||
|
||||
### Claude Desktop MCP Config
|
||||
|
||||
Store API keys securely and reference them in `claude_desktop_config.json`:
|
||||
|
||||
```bash
|
||||
# Store the key
|
||||
op item create --category API_CREDENTIAL --title "My MCP Server" \
|
||||
--vault Dev api_key[password]=your-key-here
|
||||
|
||||
# Get the secret reference
|
||||
# op://Dev/My MCP Server/api_key
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"my-server": {
|
||||
"command": "op",
|
||||
"args": ["run", "--", "node", "/path/to/server.js"],
|
||||
"env": {
|
||||
"API_KEY": "op://Dev/My MCP Server/api_key"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Claude Code Shell Environment
|
||||
|
||||
```bash
|
||||
# .env.tpl (safe to commit — no real secrets)
|
||||
ANTHROPIC_API_KEY=op://Dev/Anthropic/api_key
|
||||
OPENAI_API_KEY=op://Dev/OpenAI/api_key
|
||||
|
||||
# ✅ Wrap claude with op run — secrets injected into subprocess only
|
||||
op run --env-file=.env.tpl -- claude
|
||||
|
||||
# ✅ Or export individually for interactive shell use
|
||||
export ANTHROPIC_API_KEY=$(op read "op://Dev/Anthropic/api_key")
|
||||
claude
|
||||
```
|
||||
|
||||
### In CLAUDE.md (project secrets reference)
|
||||
|
||||
```markdown
|
||||
## Secrets Setup
|
||||
Secrets are managed via 1Password. Run before working:
|
||||
```bash
|
||||
op run --env-file=.env.tpl -- claude
|
||||
```
|
||||
Do NOT commit `.env` — commit `.env.tpl` only.
|
||||
```
|
||||
|
||||
## n8n
|
||||
|
||||
### Environment Injection at Startup
|
||||
|
||||
```bash
|
||||
# n8n.env.tpl (commit this)
|
||||
N8N_ENCRYPTION_KEY=op://Dev/n8n/encryption_key
|
||||
DB_POSTGRESDB_PASSWORD=op://Dev/n8n-postgres/password
|
||||
N8N_BASIC_AUTH_PASSWORD=op://Dev/n8n/basic_auth_password
|
||||
|
||||
# docker-compose.yml startup
|
||||
op run --env-file=n8n.env.tpl -- docker compose up -d n8n
|
||||
```
|
||||
|
||||
### n8n Credential Storage via API
|
||||
|
||||
Use n8n's credential API to push secrets from 1Password into n8n:
|
||||
|
||||
```bash
|
||||
# Get secret from 1Password
|
||||
API_KEY=$(op read "op://Dev/Some Service/api_key")
|
||||
|
||||
# Push to n8n credential (HTTP Request)
|
||||
curl -s -X POST "https://n8n.example.com/api/v1/credentials" \
|
||||
-H "X-N8N-API-KEY: $(op read 'op://Dev/n8n/api_key')" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"name\": \"Service Credential\", \"type\": \"httpHeaderAuth\", \"data\": {\"name\": \"Authorization\", \"value\": \"Bearer $API_KEY\"}}"
|
||||
```
|
||||
|
||||
## Docker / Docker Compose
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
services:
|
||||
app:
|
||||
image: myapp:latest
|
||||
environment:
|
||||
DATABASE_URL: ${DATABASE_URL}
|
||||
API_KEY: ${API_KEY}
|
||||
```
|
||||
|
||||
```bash
|
||||
# .env.tpl
|
||||
DATABASE_URL=op://Dev/Postgres/connection_string
|
||||
API_KEY=op://Dev/MyApp/api_key
|
||||
|
||||
# Start with injection
|
||||
op run --env-file=.env.tpl -- docker compose up
|
||||
```
|
||||
|
||||
## Python Scripts
|
||||
|
||||
```python
|
||||
import subprocess
|
||||
|
||||
def get_secret(reference: str) -> str:
|
||||
"""Read a secret from 1Password using a secret reference."""
|
||||
result = subprocess.run(
|
||||
["op", "read", reference],
|
||||
capture_output=True, text=True, check=True
|
||||
)
|
||||
return result.stdout.strip()
|
||||
|
||||
# Usage
|
||||
api_key = get_secret("op://Dev/Anthropic/api_key")
|
||||
```
|
||||
|
||||
Or using the 1Password Python SDK (if available):
|
||||
```bash
|
||||
pip install onepassword-sdk
|
||||
```
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
import onepassword
|
||||
|
||||
async def main():
|
||||
client = await onepassword.Client.authenticate(
|
||||
auth=os.environ["OP_SERVICE_ACCOUNT_TOKEN"],
|
||||
integration_name="My Script",
|
||||
integration_version="1.0.0",
|
||||
)
|
||||
secret = await client.secrets.resolve("op://Dev/Anthropic/api_key")
|
||||
```
|
||||
|
||||
## GitHub Actions / CI
|
||||
|
||||
```yaml
|
||||
# .github/workflows/deploy.yml
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: 1password/load-secrets-action@v2
|
||||
with:
|
||||
export-env: true
|
||||
env:
|
||||
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
|
||||
ANTHROPIC_API_KEY: op://Dev/Anthropic/api_key
|
||||
DEPLOY_KEY: op://Dev/Deploy/private_key
|
||||
|
||||
- run: deploy-script.sh # ANTHROPIC_API_KEY is available
|
||||
```
|
||||
|
||||
## Shell / .zshrc Auto-Load
|
||||
|
||||
```bash
|
||||
# ~/.zshrc
|
||||
# Auto-load common dev secrets on shell start (optional — only if you trust your machine)
|
||||
load_dev_secrets() {
|
||||
if command -v op &>/dev/null && op whoami &>/dev/null 2>&1; then
|
||||
source <(op run --env-file=~/.config/dev.env.tpl -- env 2>/dev/null) && \
|
||||
echo "✅ Dev secrets loaded from 1Password"
|
||||
fi
|
||||
}
|
||||
|
||||
# Call explicitly when needed:
|
||||
alias load-secrets='load_dev_secrets'
|
||||
```
|
||||
|
||||
## Supabase
|
||||
|
||||
```bash
|
||||
# Store Supabase credentials
|
||||
op item create --category API_CREDENTIAL --title "Supabase - My Project" \
|
||||
--vault Dev \
|
||||
url[text]=https://myproject.supabase.co \
|
||||
anon_key[password]=eyJ... \
|
||||
service_key[password]=eyJ...
|
||||
|
||||
# Use in scripts
|
||||
SUPABASE_URL=$(op read "op://Dev/Supabase - My Project/url")
|
||||
SUPABASE_KEY=$(op read "op://Dev/Supabase - My Project/service_key")
|
||||
```
|
||||
|
||||
## Replit
|
||||
|
||||
Replit has its own Secrets manager, but for local dev before deploying:
|
||||
|
||||
```bash
|
||||
# Generate a .env from 1Password, then paste values into Replit Secrets UI
|
||||
op run --env-file=.env.tpl -- env | grep -E "^(ANTHROPIC|SUPABASE|N8N)"
|
||||
# Copy output values → paste into Replit Secrets one by one
|
||||
```
|
||||
|
||||
## Rotation Workflow
|
||||
|
||||
When rotating a credential:
|
||||
|
||||
```bash
|
||||
# 1. Update in the service (get new key)
|
||||
NEW_KEY="new-key-from-service"
|
||||
|
||||
# 2. Update in 1Password
|
||||
op item edit "Service Name" api_key[password]="$NEW_KEY"
|
||||
|
||||
# 3. Verify
|
||||
op read "op://Dev/Service Name/api_key"
|
||||
|
||||
# 4. Re-inject wherever used
|
||||
source <(op run --env-file=.env.tpl -- env)
|
||||
# Or restart services that use the key
|
||||
```
|
||||
171
.claude/skills/1password/references/op_commands.md
Normal file
171
.claude/skills/1password/references/op_commands.md
Normal file
@@ -0,0 +1,171 @@
|
||||
# 1Password CLI (op) Command Reference
|
||||
|
||||
## Authentication
|
||||
|
||||
```bash
|
||||
# Sign in (interactive)
|
||||
op signin
|
||||
|
||||
# Sign in to specific account
|
||||
op signin --account team-name.1password.com
|
||||
|
||||
# Check who you're signed in as
|
||||
op whoami
|
||||
|
||||
# List accounts
|
||||
op account list
|
||||
|
||||
# Service account (CI/CD — set env var, no signin needed)
|
||||
export OP_SERVICE_ACCOUNT_TOKEN="your-token"
|
||||
```
|
||||
|
||||
## Items
|
||||
|
||||
```bash
|
||||
# List items
|
||||
op item list
|
||||
op item list --vault Dev
|
||||
op item list --categories API_CREDENTIAL
|
||||
|
||||
# Get item details
|
||||
op item get "Item Title"
|
||||
op item get "Item Title" --vault Dev
|
||||
op item get "Item Title" --format json
|
||||
|
||||
# Get a specific field
|
||||
op item get "Item Title" --fields api_key
|
||||
op item get "Item Title" --fields label=api_key
|
||||
|
||||
# Read using secret reference (most common)
|
||||
op read "op://Dev/Item Title/api_key"
|
||||
|
||||
# Create item
|
||||
op item create --category API_CREDENTIAL --title "My API Key" api_key[password]=sk-abc123
|
||||
op item create --category LOGIN --title "Service Account" --vault Dev \
|
||||
username[text]=myuser password[password]=mypass
|
||||
|
||||
# Edit/update item
|
||||
op item edit "Item Title" api_key[password]=new-value
|
||||
op item edit "Item Title" --vault Dev new_field[text]=value
|
||||
|
||||
# Delete item
|
||||
op item delete "Item Title"
|
||||
op item delete "Item Title" --vault Dev
|
||||
|
||||
# Move item to different vault
|
||||
op item move "Item Title" --current-vault Dev --destination-vault Personal
|
||||
```
|
||||
|
||||
## Vaults
|
||||
|
||||
```bash
|
||||
# List vaults
|
||||
op vault list
|
||||
op vault list --format json
|
||||
|
||||
# Create vault
|
||||
op vault create "New Vault"
|
||||
|
||||
# Get vault details
|
||||
op vault get "Vault Name"
|
||||
```
|
||||
|
||||
## Secrets Injection
|
||||
|
||||
```bash
|
||||
# Run command with secrets from .env template (RECOMMENDED)
|
||||
op run --env-file=.env.tpl -- your-command arg1 arg2
|
||||
|
||||
# Inject into Docker
|
||||
op run --env-file=.env.tpl -- docker compose up
|
||||
|
||||
# Inject a single reference via env var (op run picks up op:// values automatically)
|
||||
export API_KEY="op://Dev/MyApp/api_key"
|
||||
op run -- node app.js # API_KEY is resolved at runtime
|
||||
|
||||
# ⚠️ AVOID: sourcing op run output into the current shell
|
||||
# source <(op run --env-file=.env.tpl -- env) ← UNSAFE
|
||||
# If secret values contain $(...) or backticks, they execute as shell code.
|
||||
# Use 'op run -- your-command' instead (secrets stay in subprocess only).
|
||||
```
|
||||
|
||||
## Password Generation
|
||||
|
||||
```bash
|
||||
# Generate at item creation time (no standalone command)
|
||||
op item create --category PASSWORD --title "Generated Secret" \
|
||||
--generate-password='letters,digits,symbols,32'
|
||||
|
||||
# Generate with custom recipe
|
||||
op item create --category LOGIN --title "My Login" \
|
||||
--generate-password='letters,digits,20'
|
||||
|
||||
# Or use openssl for scripted generation
|
||||
openssl rand -base64 32 | tr -d '=+/'
|
||||
```
|
||||
|
||||
## Document / File Management
|
||||
|
||||
```bash
|
||||
# Store a file
|
||||
op document create ./private-key.pem --title "SSH Private Key" --vault Dev
|
||||
|
||||
# Get a file
|
||||
op document get "SSH Private Key" --output ./private-key.pem
|
||||
|
||||
# List documents
|
||||
op document list
|
||||
```
|
||||
|
||||
## Service Accounts (CI/CD)
|
||||
|
||||
```bash
|
||||
# Create service account (in 1Password UI: Settings → Developer → Service Accounts)
|
||||
# Then set token as env var:
|
||||
export OP_SERVICE_ACCOUNT_TOKEN="ops_eyJ..."
|
||||
|
||||
# No signin needed — op commands work automatically
|
||||
op item list # works with service account token
|
||||
op read "op://vault/item/field"
|
||||
```
|
||||
|
||||
## Connect (Self-hosted, advanced)
|
||||
|
||||
```bash
|
||||
# For teams running 1Password Connect server
|
||||
export OP_CONNECT_HOST="https://your-connect-server"
|
||||
export OP_CONNECT_TOKEN="your-connect-token"
|
||||
|
||||
# Then op commands use Connect instead of 1Password.com
|
||||
op item get "Item Title"
|
||||
```
|
||||
|
||||
## Output Formats
|
||||
|
||||
Valid values: `json` or `human-readable` (default).
|
||||
|
||||
```bash
|
||||
op item list --format=json # Machine-readable JSON
|
||||
op item get "Item" --format=json # Full item JSON
|
||||
op item list # Human-readable (default)
|
||||
op vault list --format=json # Vaults as JSON
|
||||
```
|
||||
|
||||
## Useful Patterns
|
||||
|
||||
```bash
|
||||
# Find item by field value (search)
|
||||
op item list --format=json | \
|
||||
python3 -c "import sys,json; [print(i['title']) for i in json.load(sys.stdin)]"
|
||||
|
||||
# Export all items in a vault to JSON (backup)
|
||||
op item list --vault Dev --format=json | \
|
||||
python3 -c "import sys,json; ids=[i['id'] for i in json.load(sys.stdin)]"
|
||||
# (then loop to get each)
|
||||
|
||||
# Check if a specific item exists
|
||||
op item get "My Item" &>/dev/null && echo "exists" || echo "not found"
|
||||
|
||||
# Get item ID (for scripting)
|
||||
op item get "My Item" --format=json | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])"
|
||||
```
|
||||
120
.claude/skills/1password/references/secret_references.md
Normal file
120
.claude/skills/1password/references/secret_references.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# 1Password Secret References
|
||||
|
||||
Secret references are the safest way to use secrets — they point to 1Password without exposing actual values in code or config files.
|
||||
|
||||
## Syntax
|
||||
|
||||
```
|
||||
op://vault/item/field
|
||||
op://vault/item/section/field
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
```bash
|
||||
op://Dev/Anthropic/api_key
|
||||
op://Personal/AWS/access_key_id
|
||||
op://Dev/Supabase/section/service_key
|
||||
```
|
||||
|
||||
## Reading a Secret Reference
|
||||
|
||||
```bash
|
||||
# Single secret
|
||||
op read "op://Dev/Anthropic/api_key"
|
||||
|
||||
# Into a variable
|
||||
export ANTHROPIC_API_KEY=$(op read "op://Dev/Anthropic/api_key")
|
||||
|
||||
# Multiple secrets via op run
|
||||
op run --env-file=.env.tpl -- your-command
|
||||
```
|
||||
|
||||
## .env Template Files
|
||||
|
||||
Store references in a `.env.tpl` file (safe to commit to **private** repos):
|
||||
|
||||
> **Privacy note:** `.env.tpl` contains your vault names, item names, and field names —
|
||||
> e.g. `op://Dev/Anthropic/api_key`. This reveals the structure of your 1Password vault
|
||||
> to anyone who can read the file. For **private repos**, this is fine. For **public repos**,
|
||||
> consider whether your vault/item naming reveals anything sensitive (client names, internal
|
||||
> service names, etc.). Real secret values are never exposed — only the structure.
|
||||
|
||||
```bash
|
||||
# .env.tpl — commit this
|
||||
ANTHROPIC_API_KEY=op://Dev/Anthropic/api_key
|
||||
N8N_API_KEY=op://Dev/n8n/api_key
|
||||
SUPABASE_SERVICE_KEY=op://Dev/Supabase/service_key
|
||||
NOTION_TOKEN=op://Dev/Notion/api_token
|
||||
```
|
||||
|
||||
Then inject at runtime:
|
||||
```bash
|
||||
# ✅ RECOMMENDED — run your command with secrets injected into subprocess only
|
||||
op run --env-file=.env.tpl -- npm start
|
||||
op run --env-file=.env.tpl -- node server.js
|
||||
op run --env-file=.env.tpl -- docker compose up
|
||||
|
||||
# ✅ OK — read a single secret into a variable for immediate use
|
||||
export ANTHROPIC_API_KEY=$(op read "op://Dev/Anthropic/api_key")
|
||||
|
||||
# ⚠️ AVOID — sourcing op run output exposes secrets in current shell
|
||||
# and is unsafe if any secret value contains shell metacharacters like $(...):
|
||||
# source <(op run --env-file=.env.tpl -- env) ← DON'T DO THIS
|
||||
|
||||
# ⚠️ AVOID — writing resolved secrets to disk (don't commit .env)
|
||||
# op run --env-file=.env.tpl -- env > .env ← only if truly necessary
|
||||
```
|
||||
|
||||
## In Config Files
|
||||
|
||||
Claude Desktop (`claude_desktop_config.json`):
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"my-server": {
|
||||
"command": "op",
|
||||
"args": ["run", "--", "node", "server.js"],
|
||||
"env": {
|
||||
"API_KEY": "op://Dev/MyServer/api_key"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Docker Compose:
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
image: myapp
|
||||
environment:
|
||||
- DATABASE_URL=op://Dev/Postgres/connection_string
|
||||
```
|
||||
Run with: `op run -- docker compose up`
|
||||
|
||||
n8n (environment injection):
|
||||
```bash
|
||||
# In your n8n startup script
|
||||
op run --env-file=n8n.env.tpl -- docker compose up n8n
|
||||
```
|
||||
|
||||
## Finding Field Names
|
||||
|
||||
```bash
|
||||
# List all fields in an item
|
||||
op item get "Item Name" --format=json | \
|
||||
python3 -c "import sys,json; [print(f['label']) for f in json.load(sys.stdin)['fields'] if f.get('value')]"
|
||||
|
||||
# Or view interactively
|
||||
op item get "Item Name"
|
||||
```
|
||||
|
||||
## Common Field Names by Category
|
||||
|
||||
| Category | Common Fields |
|
||||
|----------|---------------|
|
||||
| API_CREDENTIAL | `api_key`, `credential`, `token` |
|
||||
| LOGIN | `username`, `password` |
|
||||
| DATABASE | `connection_string`, `host`, `port`, `username`, `password` |
|
||||
| SECURE_NOTE | `notesPlain` |
|
||||
| SERVER | `hostname`, `port`, `username`, `password` |
|
||||
75
.claude/skills/1password/scripts/check_setup.sh
Executable file
75
.claude/skills/1password/scripts/check_setup.sh
Executable file
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
# check_setup.sh — Verify 1Password CLI is installed and authenticated
|
||||
# Usage: bash check_setup.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
PASS=0
|
||||
FAIL=0
|
||||
|
||||
check() {
|
||||
local label="$1"
|
||||
local cmd="$2"
|
||||
if eval "$cmd" &>/dev/null; then
|
||||
echo " ✅ $label"
|
||||
((PASS++)) || true
|
||||
else
|
||||
echo " ❌ $label"
|
||||
((FAIL++)) || true
|
||||
fi
|
||||
}
|
||||
|
||||
echo "=== 1Password CLI Setup Check ==="
|
||||
echo ""
|
||||
|
||||
# 1. CLI installed
|
||||
check "op CLI installed" "command -v op"
|
||||
|
||||
# 2. Version
|
||||
if command -v op &>/dev/null; then
|
||||
echo " ℹ️ Version: $(op --version)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "--- Authentication ---"
|
||||
|
||||
# 3. Signed in
|
||||
check "Signed in to 1Password" "op account list 2>/dev/null | grep -q '.'"
|
||||
|
||||
# 4. Can list vaults
|
||||
check "Can list vaults" "op vault list &>/dev/null"
|
||||
|
||||
# Show accounts if authenticated
|
||||
if op account list &>/dev/null 2>&1; then
|
||||
echo ""
|
||||
echo " Accounts:"
|
||||
op account list 2>/dev/null | tail -n +2 | while read -r line; do
|
||||
echo " • $line"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo " Vaults:"
|
||||
op vault list --format=json 2>/dev/null | \
|
||||
python3 -c "import sys,json; [print(f' • {v[\"name\"]} ({v[\"id\"]})') for v in json.load(sys.stdin)]" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "--- Environment ---"
|
||||
|
||||
# 5. OP_SERVICE_ACCOUNT_TOKEN (CI/CD pattern)
|
||||
if [[ -n "${OP_SERVICE_ACCOUNT_TOKEN:-}" ]]; then
|
||||
echo " ✅ OP_SERVICE_ACCOUNT_TOKEN is set (service account mode)"
|
||||
else
|
||||
echo " ℹ️ OP_SERVICE_ACCOUNT_TOKEN not set (interactive/desktop app mode)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "==================================="
|
||||
if [[ $FAIL -eq 0 ]]; then
|
||||
echo "✅ All checks passed. 1Password CLI is ready."
|
||||
else
|
||||
echo "⚠️ $FAIL check(s) failed. See above."
|
||||
echo ""
|
||||
echo "Install: https://developer.1password.com/docs/cli/get-started/"
|
||||
echo "Sign in: op signin"
|
||||
fi
|
||||
142
.claude/skills/1password/scripts/env_from_op.sh
Executable file
142
.claude/skills/1password/scripts/env_from_op.sh
Executable file
@@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env bash
|
||||
# env_from_op.sh — Generate a .env file from 1Password items
|
||||
#
|
||||
# Usage:
|
||||
# bash env_from_op.sh # Interactive: prompts for vault + items
|
||||
# bash env_from_op.sh --vault Dev # Use specific vault
|
||||
# bash env_from_op.sh --item "My Project" # Export all fields from one item
|
||||
# bash env_from_op.sh --output .env # Write to file (default: .env)
|
||||
# bash env_from_op.sh --dry-run # Print without writing
|
||||
#
|
||||
# Output format:
|
||||
# FIELD_NAME=op://Vault/Item/field # Secret references (safest)
|
||||
# FIELD_NAME=actual_value # Resolved values (with --resolve)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
VAULT=""
|
||||
ITEM=""
|
||||
OUTPUT=".env"
|
||||
DRY_RUN=false
|
||||
RESOLVE=false
|
||||
|
||||
# Parse args
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--vault) VAULT="$2"; shift 2 ;;
|
||||
--item) ITEM="$2"; shift 2 ;;
|
||||
--output) OUTPUT="$2"; shift 2 ;;
|
||||
--dry-run) DRY_RUN=true; shift ;;
|
||||
--resolve) RESOLVE=true; shift ;;
|
||||
*) echo "Unknown option: $1"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check op is available
|
||||
if ! command -v op &>/dev/null; then
|
||||
echo "❌ 1Password CLI (op) not found. Install: https://developer.1password.com/docs/cli/get-started/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If no item specified, list items and prompt
|
||||
if [[ -z "$ITEM" ]]; then
|
||||
echo "Available items in vault '${VAULT:-all vaults}':"
|
||||
if [[ -n "$VAULT" ]]; then
|
||||
op item list --vault "$VAULT" --format=json | \
|
||||
python3 -c "import sys,json; [print(f' {i[\"title\"]}') for i in json.load(sys.stdin)]"
|
||||
else
|
||||
op item list --format=json | \
|
||||
python3 -c "import sys,json; [print(f' [{i[\"vault\"][\"name\"]}] {i[\"title\"]}') for i in json.load(sys.stdin)]"
|
||||
fi
|
||||
echo ""
|
||||
read -rp "Enter item title: " ITEM
|
||||
fi
|
||||
|
||||
echo "Fetching '${ITEM}' from 1Password..."
|
||||
|
||||
# Get item as JSON
|
||||
if [[ -n "$VAULT" ]]; then
|
||||
ITEM_JSON=$(op item get "$ITEM" --vault "$VAULT" --format=json)
|
||||
else
|
||||
ITEM_JSON=$(op item get "$ITEM" --format=json)
|
||||
fi
|
||||
|
||||
VAULT_NAME=$(echo "$ITEM_JSON" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['vault']['name'])")
|
||||
ITEM_TITLE=$(echo "$ITEM_JSON" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['title'])")
|
||||
|
||||
# Build .env content
|
||||
ENV_CONTENT=$(echo "$ITEM_JSON" | python3 - <<'PYEOF'
|
||||
import sys, json, re
|
||||
|
||||
data = json.load(sys.stdin)
|
||||
vault = data['vault']['name']
|
||||
title = data['title']
|
||||
lines = []
|
||||
|
||||
SKIP_LABELS = {'username', 'password', 'notesPlain', 'notes'}
|
||||
SKIP_TYPES = {'CONCEALED'} if False else set() # resolved mode: don't skip
|
||||
|
||||
for field in data.get('fields', []):
|
||||
label = field.get('label', '')
|
||||
value = field.get('value', '')
|
||||
field_id = field.get('id', '')
|
||||
ftype = field.get('type', '')
|
||||
|
||||
# Skip empty, metadata, or UI-only fields
|
||||
if not value or not label:
|
||||
continue
|
||||
if label.lower() in {'username', 'notesplain', 'notes', 'password'} and ftype not in {'CONCEALED', 'URL'}:
|
||||
continue
|
||||
|
||||
# Convert label to ENV_VAR format
|
||||
env_key = re.sub(r'[^A-Z0-9_]', '_', label.upper().replace(' ', '_').replace('-', '_'))
|
||||
env_key = re.sub(r'_+', '_', env_key).strip('_')
|
||||
|
||||
# Use secret reference (safer than raw value)
|
||||
ref = f"op://{vault}/{title}/{label}"
|
||||
lines.append(f"{env_key}={ref}")
|
||||
|
||||
print('\n'.join(lines))
|
||||
PYEOF
|
||||
)
|
||||
|
||||
# Handle resolve flag — replace refs with real values
|
||||
if $RESOLVE; then
|
||||
echo "⚠️ Writing resolved values (actual secrets). Handle carefully."
|
||||
FINAL_CONTENT=""
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" =~ ^([A-Z_]+)=(op://.+)$ ]]; then
|
||||
key="${BASH_REMATCH[1]}"
|
||||
ref="${BASH_REMATCH[2]}"
|
||||
value=$(op read "$ref" 2>/dev/null || echo "ERROR_READING")
|
||||
FINAL_CONTENT+="${key}=${value}"$'\n'
|
||||
else
|
||||
FINAL_CONTENT+="$line"$'\n'
|
||||
fi
|
||||
done <<< "$ENV_CONTENT"
|
||||
ENV_CONTENT="$FINAL_CONTENT"
|
||||
fi
|
||||
|
||||
# Header
|
||||
HEADER="# Generated from 1Password: ${VAULT_NAME}/${ITEM_TITLE}
|
||||
# Generated: $(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
# Load with: op run --env-file=.env -- <command>
|
||||
# or: eval \$(op run --env-file=.env -- env | grep KEY)
|
||||
|
||||
"
|
||||
|
||||
FULL_CONTENT="${HEADER}${ENV_CONTENT}"
|
||||
|
||||
if $DRY_RUN; then
|
||||
echo ""
|
||||
echo "--- .env preview ---"
|
||||
echo "$FULL_CONTENT"
|
||||
echo "--- end ---"
|
||||
else
|
||||
echo "$FULL_CONTENT" > "$OUTPUT"
|
||||
echo "✅ Written to $OUTPUT (${#ENV_CONTENT} chars, $(echo "$ENV_CONTENT" | grep -c '=' || true) vars)"
|
||||
echo ""
|
||||
echo "To use:"
|
||||
echo " op run --env-file=$OUTPUT -- your-command"
|
||||
echo " source <(op run --env-file=$OUTPUT -- env)"
|
||||
fi
|
||||
52
.claude/skills/1password/scripts/launch-in-terminal.sh
Executable file
52
.claude/skills/1password/scripts/launch-in-terminal.sh
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env bash
|
||||
# launch-in-terminal.sh — Open a script in a NEW Terminal.app window
|
||||
#
|
||||
# This is how the 1Password skill keeps secrets OUT of Claude Code.
|
||||
# Claude generates the script, then calls this launcher.
|
||||
# The script runs in Terminal.app — Claude never sees what you type.
|
||||
#
|
||||
# Usage:
|
||||
# bash launch-in-terminal.sh /path/to/script.sh
|
||||
# bash launch-in-terminal.sh /path/to/script.sh "window title"
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_PATH="${1:-}"
|
||||
TITLE="${2:-1Password Setup}"
|
||||
|
||||
if [[ -z "$SCRIPT_PATH" ]]; then
|
||||
echo "Usage: bash launch-in-terminal.sh /path/to/script.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$SCRIPT_PATH" ]]; then
|
||||
echo "❌ Script not found: $SCRIPT_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chmod +x "$SCRIPT_PATH"
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " Opening Terminal.app to collect secrets"
|
||||
echo " Script: $SCRIPT_PATH"
|
||||
echo ""
|
||||
echo " ⚠️ Type your secrets in the Terminal"
|
||||
echo " window that is about to open."
|
||||
echo " Claude Code cannot see that window."
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
osascript <<APPLESCRIPT
|
||||
tell application "Terminal"
|
||||
activate
|
||||
set newTab to do script "echo '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'; echo ' ${TITLE}'; echo ' Type secrets here — Claude Code cannot see this window'; echo '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'; echo ''; bash ${SCRIPT_PATH}"
|
||||
end tell
|
||||
APPLESCRIPT
|
||||
|
||||
echo "✅ Terminal.app opened. Complete the prompts there, then return here."
|
||||
echo " (This window will wait for you to press Enter when done)"
|
||||
echo ""
|
||||
read -rp "Press Enter once you've finished in Terminal.app... "
|
||||
echo ""
|
||||
echo "Continuing..."
|
||||
124
.claude/skills/1password/scripts/store-mcp-credentials.sh
Executable file
124
.claude/skills/1password/scripts/store-mcp-credentials.sh
Executable file
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env bash
|
||||
# store-mcp-credentials.sh — Store MCP server credentials in 1Password
|
||||
#
|
||||
# ⚠️ RUN THIS IN TERMINAL.APP — NOT IN CLAUDE CODE
|
||||
# Claude Code can see everything typed in its terminal.
|
||||
# Open Terminal.app separately, then run this script.
|
||||
#
|
||||
# Usage (Claude will generate a pre-filled version for you):
|
||||
# bash store-mcp-credentials.sh \
|
||||
# --vault Dev \
|
||||
# --item "My MCP Server" \
|
||||
# --set "url=https://api.example.com" \
|
||||
# --set "log_level=error" \
|
||||
# --secret "api_key" \
|
||||
# --secret "webhook_secret"
|
||||
#
|
||||
# Options:
|
||||
# --vault 1Password vault name (default: Dev)
|
||||
# --item Item title in 1Password
|
||||
# --set Non-secret field: key=value (pre-filled, visible)
|
||||
# --secret Secret field: prompted with hidden input
|
||||
# --update Update existing item instead of creating new
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
VAULT="Dev"
|
||||
ITEM=""
|
||||
UPDATE=false
|
||||
declare -a SET_FIELDS=()
|
||||
declare -a SECRET_FIELDS=()
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--vault) VAULT="$2"; shift 2 ;;
|
||||
--item) ITEM="$2"; shift 2 ;;
|
||||
--set) SET_FIELDS+=("$2"); shift 2 ;;
|
||||
--secret) SECRET_FIELDS+=("$2"); shift 2 ;;
|
||||
--update) UPDATE=true; shift ;;
|
||||
*) echo "Unknown option: $1"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ -z "$ITEM" ]]; then
|
||||
read -rp "Item title in 1Password: " ITEM
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " Storing: $ITEM"
|
||||
echo " Vault: $VAULT"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
|
||||
# Show pre-filled fields
|
||||
if [[ ${#SET_FIELDS[@]} -gt 0 ]]; then
|
||||
echo "Pre-filled fields:"
|
||||
for field in "${SET_FIELDS[@]}"; do
|
||||
key="${field%%=*}"
|
||||
val="${field#*=}"
|
||||
echo " $key = $val"
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Prompt for secret fields
|
||||
declare -a SECRET_VALUES=()
|
||||
if [[ ${#SECRET_FIELDS[@]} -gt 0 ]]; then
|
||||
echo "Enter secret values (input is hidden):"
|
||||
for field in "${SECRET_FIELDS[@]}"; do
|
||||
read -rsp " $field: " secret_val
|
||||
echo ""
|
||||
SECRET_VALUES+=("${field}[password]=${secret_val}")
|
||||
done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Build op field args for non-secret fields
|
||||
declare -a OP_FIELDS=()
|
||||
for field in "${SET_FIELDS[@]}"; do
|
||||
key="${field%%=*}"
|
||||
val="${field#*=}"
|
||||
OP_FIELDS+=("${key}[text]=${val}")
|
||||
done
|
||||
|
||||
# Combine all fields
|
||||
ALL_FIELDS=("${OP_FIELDS[@]+"${OP_FIELDS[@]}"}" "${SECRET_VALUES[@]+"${SECRET_VALUES[@]}"}")
|
||||
|
||||
echo "Saving to 1Password..."
|
||||
|
||||
if $UPDATE; then
|
||||
op item edit "$ITEM" --vault "$VAULT" "${ALL_FIELDS[@]}"
|
||||
echo ""
|
||||
echo "✅ Updated '$ITEM' in vault '$VAULT'"
|
||||
else
|
||||
# Try create, fall back to update if already exists
|
||||
if op item get "$ITEM" --vault "$VAULT" &>/dev/null 2>&1; then
|
||||
echo " Item already exists — updating instead..."
|
||||
op item edit "$ITEM" --vault "$VAULT" "${ALL_FIELDS[@]}"
|
||||
echo ""
|
||||
echo "✅ Updated '$ITEM' in vault '$VAULT'"
|
||||
else
|
||||
op item create \
|
||||
--category API_CREDENTIAL \
|
||||
--title "$ITEM" \
|
||||
--vault "$VAULT" \
|
||||
"${ALL_FIELDS[@]}"
|
||||
echo ""
|
||||
echo "✅ Created '$ITEM' in vault '$VAULT'"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Secret references for your config:"
|
||||
for field in "${SET_FIELDS[@]}"; do
|
||||
key="${field%%=*}"
|
||||
echo " op://${VAULT}/${ITEM}/${key}"
|
||||
done
|
||||
for field in "${SECRET_FIELDS[@]}"; do
|
||||
echo " op://${VAULT}/${ITEM}/${field}"
|
||||
done
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " Done. You can close this terminal."
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
91
.claude/skills/1password/scripts/store_secret.sh
Executable file
91
.claude/skills/1password/scripts/store_secret.sh
Executable file
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env bash
|
||||
# store_secret.sh — Store or update a secret in 1Password
|
||||
#
|
||||
# Usage:
|
||||
# bash store_secret.sh --title "My API Key" --field "api_key" --value "sk-..."
|
||||
# bash store_secret.sh --title "Project Creds" --vault Dev --category API_CREDENTIAL
|
||||
# bash store_secret.sh --update --title "Existing Item" --field "api_key" --value "new-value"
|
||||
# bash store_secret.sh --from-env MY_VAR # Store from environment variable
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
TITLE=""
|
||||
FIELD="credential"
|
||||
VALUE=""
|
||||
VAULT=""
|
||||
CATEGORY="API_CREDENTIAL"
|
||||
UPDATE=false
|
||||
FROM_ENV=""
|
||||
GENERATE=false
|
||||
GENERATE_LENGTH=32
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--title) TITLE="$2"; shift 2 ;;
|
||||
--field) FIELD="$2"; shift 2 ;;
|
||||
--value) VALUE="$2"; shift 2 ;;
|
||||
--vault) VAULT="$2"; shift 2 ;;
|
||||
--category) CATEGORY="$2"; shift 2 ;;
|
||||
--update) UPDATE=true; shift ;;
|
||||
--from-env) FROM_ENV="$2"; shift 2 ;;
|
||||
--generate) GENERATE=true; shift ;;
|
||||
--length) GENERATE_LENGTH="$2"; shift 2 ;;
|
||||
*) echo "Unknown option: $1"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Validate
|
||||
if [[ -z "$TITLE" ]]; then
|
||||
read -rp "Item title: " TITLE
|
||||
fi
|
||||
|
||||
# Get value from env var if requested
|
||||
if [[ -n "$FROM_ENV" ]]; then
|
||||
VALUE="${!FROM_ENV:-}"
|
||||
if [[ -z "$VALUE" ]]; then
|
||||
echo "❌ Environment variable $FROM_ENV is not set or empty"
|
||||
exit 1
|
||||
fi
|
||||
FIELD="${FROM_ENV}"
|
||||
echo "Using value from \$$FROM_ENV"
|
||||
fi
|
||||
|
||||
# Generate a secure credential if requested
|
||||
if $GENERATE; then
|
||||
VALUE=$(openssl rand -base64 "$GENERATE_LENGTH" | tr -d '=+/' | head -c "$GENERATE_LENGTH")
|
||||
echo "🔐 Generated secure credential ($GENERATE_LENGTH chars)"
|
||||
fi
|
||||
|
||||
# Prompt for value if still empty
|
||||
if [[ -z "$VALUE" ]]; then
|
||||
read -rsp "Value (hidden): " VALUE
|
||||
echo ""
|
||||
fi
|
||||
|
||||
VAULT_FLAG=""
|
||||
[[ -n "$VAULT" ]] && VAULT_FLAG="--vault $VAULT"
|
||||
|
||||
if $UPDATE; then
|
||||
echo "Updating '${FIELD}' in '${TITLE}'..."
|
||||
op item edit "$TITLE" $VAULT_FLAG "${FIELD}[password]=${VALUE}"
|
||||
echo "✅ Updated '${FIELD}' in '${TITLE}'"
|
||||
else
|
||||
echo "Creating '${TITLE}' in 1Password..."
|
||||
RESULT=$(op item create \
|
||||
--category "$CATEGORY" \
|
||||
--title "$TITLE" \
|
||||
$VAULT_FLAG \
|
||||
"${FIELD}[password]=${VALUE}" \
|
||||
--format=json)
|
||||
|
||||
ITEM_ID=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
|
||||
VAULT_NAME=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin)['vault']['name'])")
|
||||
|
||||
echo "✅ Created '${TITLE}' (ID: ${ITEM_ID})"
|
||||
echo ""
|
||||
echo "Secret reference:"
|
||||
echo " op://${VAULT_NAME}/${TITLE}/${FIELD}"
|
||||
echo ""
|
||||
echo "Read it back:"
|
||||
echo " op read \"op://${VAULT_NAME}/${TITLE}/${FIELD}\""
|
||||
fi
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -53,6 +53,7 @@ build/
|
||||
*.sqlite
|
||||
logs/
|
||||
.claude/tokens.json
|
||||
**/.tokens.json
|
||||
.claude/context-recall-config.env
|
||||
.claude/context-recall-config.env.backup
|
||||
.claude/context-cache/
|
||||
@@ -63,3 +64,7 @@ api/.env
|
||||
.mcp.json
|
||||
Pictures/
|
||||
.grepai/
|
||||
# Radio processor
|
||||
projects/radio-show/audio-processor/test-data/*.mp3
|
||||
projects/radio-show/audio-processor/*.egg-info/
|
||||
|
||||
|
||||
@@ -37,16 +37,16 @@ Windows> choco install git python nodejs
|
||||
```bash
|
||||
# Windows
|
||||
Windows> cd D:\
|
||||
Windows> git clone ssh://azcomputerguru@172.16.3.20:2222/azcomputerguru/claudetools.git ClaudeTools
|
||||
Windows> git clone https://git.azcomputerguru.com/azcomputerguru/claudetools.git ClaudeTools
|
||||
Windows> cd ClaudeTools
|
||||
|
||||
# Mac
|
||||
Mac> cd ~/Projects # or wherever you want it
|
||||
Mac> git clone ssh://azcomputerguru@172.16.3.20:2222/azcomputerguru/claudetools.git ClaudeTools
|
||||
Mac> git clone https://git.azcomputerguru.com/azcomputerguru/claudetools.git ClaudeTools
|
||||
Mac> cd ClaudeTools
|
||||
```
|
||||
|
||||
**Note:** You'll need SSH access to the Gitea server (172.16.3.20:2222)
|
||||
**Note:** Uses HTTPS to Gitea at git.azcomputerguru.com
|
||||
|
||||
**For This Guide:**
|
||||
- Windows path: `D:\ClaudeTools`
|
||||
|
||||
BIN
Test Datasheets/DF-Test-Detail.PDF
Normal file
BIN
Test Datasheets/DF-Test-Detail.PDF
Normal file
Binary file not shown.
80
Test Datasheets/DFWDS/DFWDS_NAMES.txt
Normal file
80
Test Datasheets/DFWDS/DFWDS_NAMES.txt
Normal file
@@ -0,0 +1,80 @@
|
||||
DATASHEET FOLDER NAME,X:\Test_Datasheets
|
||||
INVALID FILE MOVE FOLDER,X:\Bad_Datasheets
|
||||
LOG FILE NAME,DFWDS
|
||||
LOG FILE FOLDER,X:\Datasheets_Log
|
||||
WEB FOLDER,X:\For_Web
|
||||
OPERATION,WEBMOVE
|
||||
|
||||
Last updated: 2015-06-08
|
||||
|
||||
The first six lines of this file are folder and file names required by
|
||||
the Dataforth Website Datasheet program (DFWDS.exe). Each line consists
|
||||
of the parameter name (in all CAPS), followed by a comma, followed by
|
||||
the file or folder name (not in quotes) or operation. A space is
|
||||
allowed after the comma separator.
|
||||
|
||||
The six lines parameter lines must contain only the allowed parameters
|
||||
and data, in this specified format, for the program to operate properly.
|
||||
Any lines below these six lines are not read by the program, and can
|
||||
consist of comments or instructions (such as these).
|
||||
|
||||
The location and name of this file (usually C:\DFWDS\DFWDS_NAMES.TXT) is
|
||||
hardcoded in the program.
|
||||
|
||||
Descriptions of the six required lines (along with the required parameter
|
||||
names) are shown below:
|
||||
|
||||
First line:
|
||||
-----------
|
||||
DATASHEET FOLDER NAME: This is the location of the folder containing the
|
||||
datasheet files that will eventually be copied to the Dataforth website.
|
||||
|
||||
Second line:
|
||||
------------
|
||||
INVALID FILE MOVE FOLDER: This is the location of the folder to which
|
||||
invalid files in the datasheet folder will be moved.
|
||||
|
||||
Third line:
|
||||
-----------
|
||||
LOG FILE NAME: This is the name of the file that logs the operation of the
|
||||
Dataforth Website Datasheet program (DFWDS.exe), including invalid file
|
||||
moves and datasheet file renaming. NOTE: This is the file name (only),
|
||||
and does NOT include the ".log" extension.
|
||||
|
||||
Fourth line:
|
||||
------------
|
||||
LOG FILE FOLDER: This is the location of the folder containing the log
|
||||
file for the DFWDS.exe program.
|
||||
|
||||
Fifth line:
|
||||
WEB FOLDER: This is the location of the folder to which the valid
|
||||
datasheet files (including renamed files) are moved if the "OPERATION"
|
||||
parameter (see below) is "WEBMOVE".
|
||||
|
||||
Sixth line:
|
||||
-----------
|
||||
OPERATION: This parameter controls the operation of the program, and
|
||||
can only be one of the values described below:
|
||||
-------------------------------------
|
||||
COUNT causes the program to only count the invalid files
|
||||
and files that should be renamed.
|
||||
|
||||
LISTALL causes the program to list all of the files found in the
|
||||
datasheet folder.
|
||||
|
||||
LISTBAD causes the program to list all of the invalid ("bad") files
|
||||
found in the datasheet folder.
|
||||
|
||||
LISTRENAME causes the program to list all of the datasheet files in
|
||||
the datasheet folder that have DOS-encoded names that need to be
|
||||
renamed to match the module serial number contained in the file.
|
||||
|
||||
INPLACE renames the appropriate files in their current directory
|
||||
(specified by the "DATASHEET FOLDER NAME" parameter - see above), but
|
||||
moves the invalid files to the directory specified by the
|
||||
"INVALID FILE MOVE FOLDER" parameter (see above).
|
||||
|
||||
WEBMOVE moves the invalid files to the "INVALID FILE MOVE FOLDER"
|
||||
directory, but also moves the valid datasheet files (including those
|
||||
that have been renamed) to the folder specified by the "WEB FOLDER"
|
||||
parameter (see above).
|
||||
1388
Test Datasheets/QB-Source/DB8BMAIN.BAS
Normal file
1388
Test Datasheets/QB-Source/DB8BMAIN.BAS
Normal file
File diff suppressed because it is too large
Load Diff
2380
Test Datasheets/QB-Source/KDSCOUT1.BAS
Normal file
2380
Test Datasheets/QB-Source/KDSCOUT1.BAS
Normal file
File diff suppressed because it is too large
Load Diff
3168
Test Datasheets/QB-Source/NLIBATED-DSCA.BAS
Normal file
3168
Test Datasheets/QB-Source/NLIBATED-DSCA.BAS
Normal file
File diff suppressed because it is too large
Load Diff
3222
Test Datasheets/QB-Source/NLIBATED-DSCT.BAS
Normal file
3222
Test Datasheets/QB-Source/NLIBATED-DSCT.BAS
Normal file
File diff suppressed because it is too large
Load Diff
3223
Test Datasheets/QB-Source/NLIBATED.BAS
Normal file
3223
Test Datasheets/QB-Source/NLIBATED.BAS
Normal file
File diff suppressed because it is too large
Load Diff
3506
Test Datasheets/QB-Source/TEST5B1E.BAS
Normal file
3506
Test Datasheets/QB-Source/TEST5B1E.BAS
Normal file
File diff suppressed because it is too large
Load Diff
3367
Test Datasheets/QB-Source/TEST5B2E.BAS
Normal file
3367
Test Datasheets/QB-Source/TEST5B2E.BAS
Normal file
File diff suppressed because it is too large
Load Diff
1731
Test Datasheets/QB-Source/TEST7B1C.BAS
Normal file
1731
Test Datasheets/QB-Source/TEST7B1C.BAS
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Test Datasheets/QB-Source/TESTPW17.BAS
Normal file
BIN
Test Datasheets/QB-Source/TESTPW17.BAS
Normal file
Binary file not shown.
3473
Test Datasheets/QB-Source/TST5SCT1.BAS
Normal file
3473
Test Datasheets/QB-Source/TST5SCT1.BAS
Normal file
File diff suppressed because it is too large
Load Diff
2052
Test Datasheets/QB-Source/TST5SCT2.BAS
Normal file
2052
Test Datasheets/QB-Source/TST5SCT2.BAS
Normal file
File diff suppressed because it is too large
Load Diff
194
Test Datasheets/README.md
Normal file
194
Test Datasheets/README.md
Normal file
@@ -0,0 +1,194 @@
|
||||
# Claude Instance Context: Test Datasheets Investigation (AD1)
|
||||
|
||||
**Purpose:** You are a Claude Code instance running on AD1 (192.168.0.27) at Dataforth's facility. Your job is to investigate the TestDataSheetUploader tool and the test datasheet workflow -- where files come from, where they go, and how this integrates with the DOS test machines.
|
||||
|
||||
**This is a temporary investigation instance.** Once findings are documented and synced to Gitea, this instance will be removed.
|
||||
|
||||
---
|
||||
|
||||
## Your Mission
|
||||
|
||||
1. **Find where test datasheets are generated** -- which machine(s), which software, what path
|
||||
2. **Find where they end up** -- the server-side path is `C:\inetpub\wwwroot\dataforth.com\WebShare\ProcessCheckOutTestFolder\` on whatever runs www.dataforth.com
|
||||
3. **Determine if this uploader is still in active use** or if the workflow changed
|
||||
4. **Document the full datasheet pipeline** -- from DOS test machine output through to the website
|
||||
5. **Sync your findings back to Gitea** so the coordinator instance can see them
|
||||
|
||||
---
|
||||
|
||||
## Gitea Sync (How to Push Findings)
|
||||
|
||||
The ClaudeTools repo is hosted on Gitea. Clone and push your findings here:
|
||||
|
||||
```bash
|
||||
# Clone the repo
|
||||
git clone https://mike%40azcomputerguru.com:Gptf%2A77ttb123%21%40%23-git@git.azcomputerguru.com/azcomputerguru/claudetools.git
|
||||
cd claudetools
|
||||
|
||||
# Your working area
|
||||
# clients/dataforth/dos-test-machines/Test Datasheets/
|
||||
|
||||
# Commit and push findings
|
||||
git add -A
|
||||
git commit -m "AD1 investigation: test datasheet pipeline findings"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
**Gitea Credentials (plaintext, temporary use only):**
|
||||
- URL: https://git.azcomputerguru.com
|
||||
- User: mike@azcomputerguru.com
|
||||
- Password: Gptf*77ttb123!@#-git
|
||||
|
||||
---
|
||||
|
||||
## Network Context (Dataforth Engineering Network)
|
||||
|
||||
| Device | IP | Role | Credentials |
|
||||
|--------|-----|------|-------------|
|
||||
| AD1 (you are here) | 192.168.0.27 | Primary Domain Controller | INTRANET\sysadmin / Paper123!@# |
|
||||
| AD2 | 192.168.0.6 | Production Server (Win Server 2008 R2) | INTRANET\sysadmin / Paper123!@# |
|
||||
| D2TESTNAS | 192.168.0.9 | TrueNAS, SMB1 proxy for DOS machines | root / (SSH key) or admin / Paper123!@#-nas |
|
||||
| DOS Stations | 192.168.0.x | ~30 DOS 6.22 test machines (TS-XX) | N/A |
|
||||
| UDM Gateway | 192.168.0.254 | UniFi Dream Machine | N/A |
|
||||
|
||||
---
|
||||
|
||||
## What We Already Know About TestDataSheetUploader
|
||||
|
||||
This is a VB.NET console app (.NET Framework 4.7.2) last built November 2, 2022.
|
||||
|
||||
### What it does
|
||||
1. Calls `https://www.dataforth.com/Services/DirectoryManifest.aspx` to get a list of files already on the web server
|
||||
2. Compares local files against that manifest (by filename, size, and last-modified date)
|
||||
3. Uploads new/changed files via `https://www.dataforth.com/Services/Uploader.aspx`
|
||||
4. Deletes files from server that no longer exist locally via `https://www.dataforth.com/Services/DeleteFile.aspx`
|
||||
5. Only processes files modified in the current year
|
||||
|
||||
### Configured paths (from app.config)
|
||||
- **Service auth:** username=DataforthWebShare, password=Data6277
|
||||
- **TestDataSheetPath:** `C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists`
|
||||
- **TestFolderPath:** `C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists`
|
||||
- **InventoryDataStagingFolder:** `C:\TestDataSheetUploader\staging`
|
||||
- **InventoryDataSourceFolder:** `C:\TestDataSheetUploader\src`
|
||||
- **InventoryDataFiles:** AvSelCat.csv, AvSelCus.csv
|
||||
|
||||
### Server-side destination (from error logs)
|
||||
```
|
||||
C:\inetpub\wwwroot\dataforth.com\WebShare\ProcessCheckOutTestFolder\
|
||||
```
|
||||
|
||||
### Key unknowns -- what you need to find out
|
||||
- **Who is "hoffm"?** Likely a Hoffman who worked at Dataforth. Which machine was this?
|
||||
- **Where do test datasheets originate?** The DOS machines run QuickBASIC data acquisition. Do they produce datasheet files?
|
||||
- **Is there a path from DOS machines -> datasheets?** The DOS machines map `T:` to `\\D2TESTNAS\TEST`. Is there a datasheets share they write to?
|
||||
- **Is the uploader still running?** Scheduled task? Manual? Last used?
|
||||
- **Where does `C:\Users\hoffm\...` map to now?** Did someone take over this role?
|
||||
|
||||
---
|
||||
|
||||
## Investigation Steps
|
||||
|
||||
### On AD1 (this machine)
|
||||
```powershell
|
||||
# Check if TestDataSheetUploader exists anywhere on this machine
|
||||
Get-ChildItem -Path C:\ -Recurse -Filter "TestDataSheetUploader*" -ErrorAction SilentlyContinue
|
||||
|
||||
# Check for Hoffman's profile or traces
|
||||
Get-ChildItem C:\Users\ -Directory
|
||||
Get-ChildItem "C:\Users\hoffm" -ErrorAction SilentlyContinue
|
||||
|
||||
# Check scheduled tasks for anything datasheet-related
|
||||
Get-ScheduledTask | Where-Object { $_.TaskName -like "*data*" -or $_.TaskName -like "*sheet*" -or $_.TaskName -like "*upload*" -or $_.TaskName -like "*sync*" }
|
||||
|
||||
# Check for IIS sites (AD1 might host www.dataforth.com)
|
||||
Import-Module WebAdministration -ErrorAction SilentlyContinue
|
||||
Get-Website -ErrorAction SilentlyContinue
|
||||
Get-ChildItem "C:\inetpub\wwwroot" -ErrorAction SilentlyContinue
|
||||
```
|
||||
|
||||
### On AD2 (192.168.0.6)
|
||||
```powershell
|
||||
# Remote into AD2 and check
|
||||
Invoke-Command -ComputerName 192.168.0.6 -Credential (Get-Credential INTRANET\sysadmin) -ScriptBlock {
|
||||
# Check for the uploader
|
||||
Get-ChildItem -Path C:\ -Recurse -Filter "TestDataSheetUploader*" -ErrorAction SilentlyContinue
|
||||
|
||||
# Check IIS
|
||||
Get-ChildItem "C:\inetpub\wwwroot" -ErrorAction SilentlyContinue
|
||||
|
||||
# Check for the WebShare path from error logs
|
||||
Get-ChildItem "C:\inetpub\wwwroot\dataforth.com\WebShare" -ErrorAction SilentlyContinue
|
||||
|
||||
# Check scheduled tasks
|
||||
Get-ScheduledTask | Where-Object { $_.TaskName -like "*data*" -or $_.TaskName -like "*upload*" }
|
||||
|
||||
# Check user profiles
|
||||
Get-ChildItem C:\Users\ -Directory
|
||||
}
|
||||
```
|
||||
|
||||
### On D2TESTNAS (192.168.0.9)
|
||||
```bash
|
||||
# SSH from AD1 or any machine with access
|
||||
ssh root@192.168.0.9
|
||||
|
||||
# Check datasheets share
|
||||
ls -la /data/datasheets/
|
||||
find /data/ -name "*datasheet*" -o -name "*TestData*" 2>/dev/null
|
||||
|
||||
# Check if DOS machines write any test output files
|
||||
ls -la /data/test/TS-27/
|
||||
find /data/test/ -name "*.pdf" -o -name "*.csv" -o -name "*.dat" 2>/dev/null
|
||||
```
|
||||
|
||||
### Check the Dataforth website services
|
||||
```powershell
|
||||
# Test if the manifest service still responds
|
||||
$cred = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("DataforthWebShare:Data6277"))
|
||||
Invoke-WebRequest -Uri "https://www.dataforth.com/Services/DirectoryManifest.aspx" -Headers @{Authorization="Basic $cred"} -Method GET -ErrorAction SilentlyContinue
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## DOS Test Machine Architecture (Full Context)
|
||||
|
||||
The DOS machines are ~30 stations running DOS 6.22 with QuickBASIC 4.5 data acquisition software.
|
||||
|
||||
```
|
||||
DOS Machines (TS-XX) --SMB1--> D2TESTNAS (192.168.0.9) --SMB2/rsync--> AD2 (192.168.0.6)
|
||||
| /data/test/ C:\Shares\test\
|
||||
| /data/datasheets/ C:\Shares\datasheets (PENDING)
|
||||
|
|
||||
+-- Map T: = \\D2TESTNAS\TEST
|
||||
+-- Run QuickBASIC data acquisition
|
||||
+-- UPDATE.BAT for remote management
|
||||
+-- TODO.BAT for remote task execution
|
||||
```
|
||||
|
||||
**Bidirectional sync** runs every 15 minutes between D2TESTNAS and AD2 via `/root/sync-to-ad2.sh`.
|
||||
|
||||
The datasheets share (`\\D2TESTNAS\datasheets` -> `/data/datasheets/`) exists on D2TESTNAS but the corresponding AD2 share (`\\AD2\datasheets`) was never created -- it's listed as a remaining task. This may be relevant to the test datasheet pipeline.
|
||||
|
||||
---
|
||||
|
||||
## Where to Save Your Findings
|
||||
|
||||
Write your investigation results to:
|
||||
```
|
||||
clients/dataforth/dos-test-machines/Test Datasheets/INVESTIGATION.md
|
||||
```
|
||||
|
||||
Include:
|
||||
- What you found on each machine
|
||||
- The complete datasheet pipeline (or what's missing/broken)
|
||||
- Whether the uploader is still active
|
||||
- Recommendations for what to do next
|
||||
|
||||
Then commit and push to Gitea using the credentials above.
|
||||
|
||||
---
|
||||
|
||||
## Contact
|
||||
|
||||
- **AJ at Dataforth** -- engineering contact, can answer questions about the test workflow
|
||||
- **Coordinator instance** -- will see your findings after you push to Gitea
|
||||
BIN
Test Datasheets/SpecData/5BMAIN.DAT
Normal file
BIN
Test Datasheets/SpecData/5BMAIN.DAT
Normal file
Binary file not shown.
BIN
Test Datasheets/SpecData/8BMAIN.DAT
Normal file
BIN
Test Datasheets/SpecData/8BMAIN.DAT
Normal file
Binary file not shown.
BIN
Test Datasheets/SpecData/DSCOUT.DAT
Normal file
BIN
Test Datasheets/SpecData/DSCOUT.DAT
Normal file
Binary file not shown.
BIN
Test Datasheets/SpecData/SCTMAIN.DAT
Normal file
BIN
Test Datasheets/SpecData/SCTMAIN.DAT
Normal file
Binary file not shown.
BIN
Test Datasheets/TestDataSheetUploader.zip
Normal file
BIN
Test Datasheets/TestDataSheetUploader.zip
Normal file
Binary file not shown.
158
Test Datasheets/TestDataSheetUploader/HTTPUploader.vb
Normal file
158
Test Datasheets/TestDataSheetUploader/HTTPUploader.vb
Normal file
@@ -0,0 +1,158 @@
|
||||
Imports System.Text
|
||||
Imports System.Net
|
||||
Imports System.IO
|
||||
|
||||
Public Class HTTPUploader
|
||||
|
||||
|
||||
|
||||
Public Shared Function UploadFile(ByVal url As String, ByVal credentials As Net.NetworkCredential, ByVal localPathFilename As String, ByVal nvc As System.Collections.Specialized.NameValueCollection, ByRef LogMessage As String) As Boolean
|
||||
Try
|
||||
'Return True
|
||||
Dim length As Long = 0
|
||||
'Dim boundary As String = "----------------------------" & Date.Now.Ticks.ToString("x")
|
||||
Dim boundary As String = "----------------------------061366199019971999"
|
||||
|
||||
Dim httpWebRequest2 As HttpWebRequest = WebRequest.Create(url)
|
||||
httpWebRequest2.ContentType = "multipart/form-data; boundary=" & boundary
|
||||
httpWebRequest2.Method = "POST"
|
||||
httpWebRequest2.KeepAlive = True
|
||||
httpWebRequest2.Credentials = credentials
|
||||
httpWebRequest2.Timeout = 900000
|
||||
|
||||
|
||||
Dim memStream As New System.IO.MemoryStream()
|
||||
|
||||
Dim boundarybytes() As Byte = System.Text.Encoding.ASCII.GetBytes(vbCrLf & "--" & boundary & vbCrLf)
|
||||
|
||||
|
||||
Dim formdataTemplate As String = vbCrLf & "--" + boundary & vbCrLf & "Content-Disposition: form-data; name=""{0}"";" & vbCrLf & vbCrLf & "{1}"
|
||||
|
||||
For Each key As String In nvc.Keys
|
||||
Dim formitem As String = String.Format(formdataTemplate, key, nvc(key))
|
||||
Dim formitembytes() As Byte = System.Text.Encoding.UTF8.GetBytes(formitem)
|
||||
memStream.Write(formitembytes, 0, formitembytes.Length)
|
||||
Next
|
||||
|
||||
|
||||
memStream.Write(boundarybytes, 0, boundarybytes.Length)
|
||||
|
||||
Dim headerTemplate As String = "Content-Disposition: form-data; name=""{0}""; filename=""{1}"" " & _
|
||||
"Content-Type: application/octet-stream" & vbCrLf & vbCrLf
|
||||
|
||||
'Content-Type: application/octet-stream
|
||||
|
||||
|
||||
'string header = string.Format(headerTemplate, "file" + i, files[i]);
|
||||
Dim header As String = String.Format(headerTemplate, "file1", localPathFilename)
|
||||
|
||||
Dim headerbytes() As Byte = System.Text.Encoding.UTF8.GetBytes(header)
|
||||
|
||||
memStream.Write(headerbytes, 0, headerbytes.Length)
|
||||
|
||||
|
||||
|
||||
Dim byteArray As Byte() = File.ReadAllBytes(localPathFilename)
|
||||
memStream.Write(byteArray, 0, byteArray.Length)
|
||||
|
||||
memStream.Write(boundarybytes, 0, boundarybytes.Length)
|
||||
|
||||
|
||||
|
||||
httpWebRequest2.ContentLength = memStream.Length + 1
|
||||
|
||||
Dim requestStream As Stream = httpWebRequest2.GetRequestStream()
|
||||
|
||||
memStream.Position = 0
|
||||
Dim tempBuffer(memStream.Length) As Byte
|
||||
memStream.Read(tempBuffer, 0, tempBuffer.Length)
|
||||
memStream.Close()
|
||||
requestStream.Write(tempBuffer, 0, tempBuffer.Length)
|
||||
requestStream.Close()
|
||||
|
||||
Dim webResponse2 As WebResponse = httpWebRequest2.GetResponse()
|
||||
|
||||
Dim stream2 As Stream = webResponse2.GetResponseStream()
|
||||
Dim reader2 As New StreamReader(stream2)
|
||||
|
||||
Dim xmlResponse As String = reader2.ReadToEnd
|
||||
|
||||
webResponse2.Close()
|
||||
httpWebRequest2 = Nothing
|
||||
webResponse2 = Nothing
|
||||
|
||||
|
||||
Dim ds As New DataSet
|
||||
ds.ReadXml(New System.Xml.XmlTextReader(New StringReader(xmlResponse)))
|
||||
|
||||
Dim responseMessage As String = ds.Tables("Result").Rows(0)("Message")
|
||||
If responseMessage = "SUCCESS" Then
|
||||
Dim uploadedFilesize As Long = ds.Tables("Result").Rows(0)("SavedFileSize")
|
||||
If My.Computer.FileSystem.GetFileInfo(localPathFilename).Length = uploadedFilesize Then
|
||||
'we are done
|
||||
Return True
|
||||
Else
|
||||
LogMessage = "Uploaded filesize (" & uploadedFilesize & ") does not match local filesize (" & My.Computer.FileSystem.GetFileInfo(localPathFilename).Length & ")"
|
||||
End If
|
||||
Else
|
||||
LogMessage = "Dataforth Service Upload Error: " & ds.Tables("Result").Rows(0)("ErrorMessage")
|
||||
End If
|
||||
Return False
|
||||
Catch ex As Exception
|
||||
LogMessage = "Exception while uploading to Dataforth Service: " & ex.ToString
|
||||
Return False
|
||||
End Try
|
||||
End Function
|
||||
|
||||
|
||||
|
||||
'Public Shared Sub _UploadVideo_(ByVal url As String, ByVal credentials As Net.NetworkCredential, ByVal localPathFilename As String, ByVal nvc As System.Collections.Specialized.NameValueCollection)
|
||||
' Try
|
||||
' Dim client As New WebClient
|
||||
' client.Credentials = credentials
|
||||
' Dim bogus As Integer = -1
|
||||
' Dim requestURL As String = url & "?ecsId=" & nvc.Get("ecsId")
|
||||
' 'requestURL = requestURL.Replace("https://", "http://")
|
||||
|
||||
' Dim response() As Byte = client.UploadFile(requestURL, localPathFilename)
|
||||
' MsgBox(System.Text.Encoding.Unicode.GetString(response))
|
||||
' Catch webEx As WebException
|
||||
' Dim thisE As String = webEx.ToString
|
||||
|
||||
' Catch ex As Exception
|
||||
|
||||
' End Try
|
||||
'End Sub
|
||||
|
||||
|
||||
'Public Shared Sub UploadVideo__(ByVal url As String, ByVal credentials As Net.NetworkCredential, ByVal localPathFilename As String, ByVal nvc As System.Collections.Specialized.NameValueCollection)
|
||||
|
||||
' Dim requestURL As String = url
|
||||
' Dim boundary As String = "----------------------------" & Date.Now.Ticks.ToString("x")
|
||||
|
||||
' 'Create Request
|
||||
' Dim webRequest As System.Net.HttpWebRequest = CType(System.Net.WebRequest.Create(requestURL), System.Net.HttpWebRequest)
|
||||
' webRequest.Credentials = credentials
|
||||
' webRequest.Timeout = 120000
|
||||
' 'System.Net.ServicePointManager.ServerCertificateValidationCallback = (Function(sender, certificate, chain, sslPolicyErrors) True)
|
||||
' 'webRequest.ContentType = "application/x-www-form-urlencoded"
|
||||
' webRequest.ContentType = "multipart/form-data; boundary=" & boundary
|
||||
' webRequest.Method = "POST"
|
||||
|
||||
|
||||
' Dim byteArray As Byte() = File.ReadAllBytes(localPathFilename)
|
||||
' webRequest.ContentLength = byteArray.Length
|
||||
' Dim dataStream As Stream = webRequest.GetRequestStream
|
||||
' dataStream.Write(byteArray, 0, byteArray.Length)
|
||||
' dataStream.Close()
|
||||
|
||||
|
||||
' ' Retrieve data from Response
|
||||
' Dim webResponse As System.Net.HttpWebResponse = CType(webRequest.GetResponse(), System.Net.HttpWebResponse)
|
||||
' Dim sr As New System.IO.StreamReader(webResponse.GetResponseStream(), System.Text.Encoding.UTF8)
|
||||
' Dim responseString As String = sr.ReadToEnd()
|
||||
' MsgBox(responseString)
|
||||
|
||||
'End Sub
|
||||
|
||||
End Class
|
||||
264
Test Datasheets/TestDataSheetUploader/Module1.vb
Normal file
264
Test Datasheets/TestDataSheetUploader/Module1.vb
Normal file
@@ -0,0 +1,264 @@
|
||||
Module Module1
|
||||
|
||||
Private processLog As System.Text.StringBuilder
|
||||
|
||||
Sub Main()
|
||||
processLog = New System.Text.StringBuilder()
|
||||
Dim appSettings As New Configuration.AppSettingsReader
|
||||
|
||||
|
||||
'for testing only
|
||||
'UploadFilesInDirectory("C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists", "TestFolder")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
'CopyInventoryFilesToStagingFolder()
|
||||
'SyncFolder("InventoryDataFolder")
|
||||
|
||||
SyncFolder("TestDataSheet")
|
||||
|
||||
|
||||
Dim logFilename As String = My.Application.Info.DirectoryPath & "\processLog." & Now.ToString("yyyy.MM.dd.HH.mm.ss") & ".txt"
|
||||
My.Computer.FileSystem.WriteAllText(logFilename, processLog.ToString, False)
|
||||
|
||||
|
||||
End Sub
|
||||
|
||||
Private Sub AddToLog(ByVal message As String, ByVal Echo As Boolean)
|
||||
processLog.Append(Now.ToString("MM/dd/YYYY HH:mm:ss | ") & message & vbCrLf)
|
||||
If Echo Then
|
||||
Console.WriteLine(message)
|
||||
End If
|
||||
End Sub
|
||||
|
||||
|
||||
Public Sub CopyInventoryFilesToStagingFolder()
|
||||
|
||||
Dim appSettings As New Configuration.AppSettingsReader
|
||||
Dim stagingFolderPath As String = appSettings.GetValue("InventoryDataStagingFolder", GetType(String))
|
||||
Dim srcFolderPath As String = appSettings.GetValue("InventoryDataSourceFolder", GetType(String))
|
||||
Dim filenamesStr As String = appSettings.GetValue("InventoryDataFiles", GetType(String))
|
||||
|
||||
Dim filenames() As String = filenamesStr.Split(",")
|
||||
|
||||
For Each thisFilename As String In filenames
|
||||
Dim src As String = srcFolderPath & "\" & thisFilename
|
||||
Dim dest As String = stagingFolderPath & "\" & thisFilename
|
||||
My.Computer.FileSystem.CopyFile(src, dest, True)
|
||||
Next
|
||||
|
||||
|
||||
End Sub
|
||||
|
||||
|
||||
Public Sub UploadFilesInDirectory(ByVal DirectoryPath As String, ByVal UploadType As String)
|
||||
|
||||
|
||||
|
||||
Dim appSettings As New Configuration.AppSettingsReader
|
||||
Dim username As String = appSettings.GetValue("ServiceUsername", GetType(String))
|
||||
Dim password As String = appSettings.GetValue("ServicePassword", GetType(String))
|
||||
Dim serviceCredentials As New Net.NetworkCredential(username, password)
|
||||
Dim url As String = appSettings.GetValue("UploaderServiceURL", GetType(String))
|
||||
|
||||
|
||||
|
||||
For Each thisFile As String In My.Computer.FileSystem.GetFiles(DirectoryPath)
|
||||
|
||||
Dim formParameters As New System.Collections.Specialized.NameValueCollection
|
||||
formParameters.Add("UploadType", UploadType)
|
||||
|
||||
Dim logMessage As New String("")
|
||||
Console.WriteLine("Uploading: " & thisFile)
|
||||
If HTTPUploader.UploadFile(url, serviceCredentials, thisFile, formParameters, logMessage) Then
|
||||
'this video is now staged
|
||||
AddToLog("Uploaded " & thisFile, True)
|
||||
|
||||
My.Computer.FileSystem.DeleteFile(thisFile)
|
||||
Else
|
||||
|
||||
AddToLog("Upload FAILED for " & thisFile, True)
|
||||
AddToLog("Upload FAIL MESSAGE: " & logMessage, False)
|
||||
Console.WriteLine("ERROR: " & logMessage)
|
||||
End If
|
||||
|
||||
|
||||
Next
|
||||
|
||||
|
||||
End Sub
|
||||
|
||||
Public Sub SyncFolder(ByVal FolderAlias As String)
|
||||
Try
|
||||
AddToLog("SyncFolder(" & FolderAlias & ") started.", True)
|
||||
'get manifest of files that are on server mirror
|
||||
Dim appSettings As New Configuration.AppSettingsReader
|
||||
Dim username As String = appSettings.GetValue("ServiceUsername", GetType(String))
|
||||
Dim password As String = appSettings.GetValue("ServicePassword", GetType(String))
|
||||
Dim serviceCredentials As New Net.NetworkCredential(username, password)
|
||||
Dim manifestServiceUrl As String = appSettings.GetValue("DirectoryManifestServiceURL", GetType(String))
|
||||
Dim uploadServiceUrl As String = appSettings.GetValue("UploaderServiceURL", GetType(String))
|
||||
Dim deleteServiceUrl As String = appSettings.GetValue("DeleteFileServiceURL", GetType(String))
|
||||
Dim testMode As Boolean = appSettings.GetValue("TestMode", GetType(Boolean))
|
||||
|
||||
'Create an XML file to post with the request
|
||||
Dim requestDS As New DataSet("Request")
|
||||
Dim requestDT As New DataTable("RequestData")
|
||||
requestDT.Columns.Add("SyncPathAlias", GetType(String))
|
||||
requestDS.Tables.Add(requestDT)
|
||||
Dim requestDR As DataRow = requestDT.NewRow
|
||||
requestDR("SyncPathAlias") = FolderAlias
|
||||
requestDT.Rows.Add(requestDR)
|
||||
|
||||
'Get Dataset from XML response
|
||||
Dim manifestXML As String = CSFramework_Utilities.XMLData.DownloadXMLWithDatasetPost(manifestServiceUrl, requestDS, serviceCredentials)
|
||||
|
||||
My.Computer.FileSystem.WriteAllText(My.Application.Info.DirectoryPath & "\manifest.xml", manifestXML, False)
|
||||
|
||||
Dim ds As DataSet = CSFramework_Utilities.XMLData.DatasetFromXML(manifestXML)
|
||||
|
||||
AddToLog("Manifest downloaded with " & ds.Tables("ContentFile").Rows.Count & " files.", True)
|
||||
|
||||
'Build a list of files that should be uploaded
|
||||
Dim filesToUpload As New List(Of String)
|
||||
|
||||
Dim localFolderPath As String = ""
|
||||
Select Case FolderAlias
|
||||
Case "TestDataSheet"
|
||||
localFolderPath = appSettings.GetValue("TestDataSheetPath", GetType(String))
|
||||
Case "TestFolder"
|
||||
localFolderPath = appSettings.GetValue("TestFolderPath", GetType(String))
|
||||
Case "InventoryDataFolder"
|
||||
localFolderPath = appSettings.GetValue("InventoryDataStagingFolder", GetType(String))
|
||||
End Select
|
||||
|
||||
Dim discoveryFileCount As Integer = 0
|
||||
Dim discoveryFileEchoCount As Integer = 1000
|
||||
|
||||
Dim sourceFolder As New System.IO.DirectoryInfo(localFolderPath)
|
||||
AddToLog("Accessing local folder: " & localFolderPath, True)
|
||||
|
||||
For Each thisLocalFileInfo As System.IO.FileInfo In sourceFolder.GetFiles
|
||||
discoveryFileCount += 1
|
||||
If discoveryFileCount = 1 Then
|
||||
AddToLog("Found at least 1 file in local folder", True)
|
||||
End If
|
||||
If discoveryFileCount = discoveryFileEchoCount Then
|
||||
AddToLog("Discovery file count: " & discoveryFileEchoCount, True)
|
||||
discoveryFileEchoCount += 1000
|
||||
End If
|
||||
'Dim thisLocalFileInfo As New System.IO.FileInfo(thisLocalFile)
|
||||
|
||||
|
||||
If thisLocalFileInfo.LastWriteTimeUtc.Year = Now.Year Then
|
||||
Dim foundMatchingFileOnServer As Boolean = False
|
||||
If ds.Tables.Contains("ContentFile") Then
|
||||
For Each dr As DataRow In ds.Tables("ContentFile").Rows
|
||||
If dr("Filename").ToString = thisLocalFileInfo.Name Then
|
||||
Dim filesize As Integer = dr("Filesize")
|
||||
Dim datelastupdated As Date = dr("DateLastUpdated")
|
||||
datelastupdated = datelastupdated.ToUniversalTime
|
||||
If filesize = thisLocalFileInfo.Length Then
|
||||
If thisLocalFileInfo.LastWriteTimeUtc.ToString("yyyy.MM.dd.HH.mm.ss") = datelastupdated.ToString("yyyy.MM.dd.HH.mm.ss") Then
|
||||
foundMatchingFileOnServer = True
|
||||
Exit For
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
Next
|
||||
End If
|
||||
If Not foundMatchingFileOnServer Then
|
||||
filesToUpload.Add(thisLocalFileInfo.FullName)
|
||||
AddToLog("Requesting upload: " & thisLocalFileInfo.Name, True)
|
||||
End If
|
||||
End If
|
||||
Next
|
||||
|
||||
AddToLog("Found " & filesToUpload.Count & " files that need to be uploaded.", True)
|
||||
|
||||
'Upload Files to Server
|
||||
If Not testMode Then
|
||||
For Each thisFile As String In filesToUpload
|
||||
Dim thisLocalFileInfo As New System.IO.FileInfo(thisFile)
|
||||
Dim formParameters As New System.Collections.Specialized.NameValueCollection
|
||||
formParameters.Add("UploadType", FolderAlias)
|
||||
'Request("LastUpdatedDate")
|
||||
formParameters.Add("LastUpdatedDate", thisLocalFileInfo.LastWriteTimeUtc.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"))
|
||||
'2015-12-11T17:38:05.9190462Z
|
||||
|
||||
Dim logMessage As New String("")
|
||||
Console.WriteLine("Uploading: " & thisFile)
|
||||
If HTTPUploader.UploadFile(uploadServiceUrl, serviceCredentials, thisFile, formParameters, logMessage) Then
|
||||
'this file is now staged
|
||||
AddToLog("Uploaded file: " & thisFile, True)
|
||||
|
||||
'My.Computer.FileSystem.DeleteFile(thisFile)
|
||||
Else
|
||||
|
||||
AddToLog("Upload FAILED for " & thisFile, True)
|
||||
AddToLog("Upload FAIL MESSAGE: " & logMessage, False)
|
||||
Console.WriteLine("ERROR: " & logMessage)
|
||||
End If
|
||||
|
||||
|
||||
Next
|
||||
End If
|
||||
|
||||
|
||||
'Create dataset for DeleteFile service
|
||||
Dim deleteDS As New DataSet("DeleteRequestData")
|
||||
|
||||
|
||||
'add request data
|
||||
Dim deleteRD As New DataTable("RequestData")
|
||||
deleteRD.Columns.Add("SyncPathAlias", GetType(String))
|
||||
Dim deleteDataDR As DataRow = deleteRD.NewRow
|
||||
deleteDataDR("SyncPathAlias") = FolderAlias
|
||||
deleteRD.Rows.Add(deleteDataDR)
|
||||
deleteDS.Tables.Add(deleteRD)
|
||||
|
||||
|
||||
'add filenames
|
||||
Dim deleteDT As New DataTable("Filenames")
|
||||
deleteDT.Columns.Add("Filename", GetType(String))
|
||||
deleteDS.Tables.Add(deleteDT)
|
||||
|
||||
If ds.Tables.Contains("ContentFile") Then
|
||||
For Each dr As DataRow In ds.Tables("ContentFile").Rows
|
||||
Dim localFileName As String = localFolderPath & "\" & dr("Filename").ToString
|
||||
If Not My.Computer.FileSystem.FileExists(localFileName) Then
|
||||
|
||||
Dim deleteDR As DataRow = deleteDT.NewRow
|
||||
deleteDR("Filename") = dr("Filename").ToString
|
||||
deleteDT.Rows.Add(deleteDR)
|
||||
|
||||
AddToLog("Requested " & FolderAlias & " Delete: " & dr("Filename").ToString, True)
|
||||
|
||||
End If
|
||||
Next
|
||||
End If
|
||||
|
||||
AddToLog("Found " & deleteDT.Rows.Count & " files to delete.", True)
|
||||
|
||||
|
||||
'Delete obsolete files that were detected
|
||||
If Not testMode Then
|
||||
If deleteDT.Rows.Count > 0 Then
|
||||
Dim deleteResponseXML As String = CSFramework_Utilities.XMLData.DownloadXMLWithDatasetPost(deleteServiceUrl, deleteDS, serviceCredentials)
|
||||
AddToLog("Obsolete " & FolderAlias & " files deleted.", True)
|
||||
Else
|
||||
AddToLog("No obsolete " & FolderAlias & " files were detected.", True)
|
||||
End If
|
||||
End If
|
||||
|
||||
Catch ex As Exception
|
||||
AddToLog("Exception in SyncFolder: " & ex.ToString, True)
|
||||
|
||||
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
|
||||
End Module
|
||||
13
Test Datasheets/TestDataSheetUploader/My Project/Application.Designer.vb
generated
Normal file
13
Test Datasheets/TestDataSheetUploader/My Project/Application.Designer.vb
generated
Normal file
@@ -0,0 +1,13 @@
|
||||
'------------------------------------------------------------------------------
|
||||
' <auto-generated>
|
||||
' This code was generated by a tool.
|
||||
' Runtime Version:4.0.30319.42000
|
||||
'
|
||||
' Changes to this file may cause incorrect behavior and will be lost if
|
||||
' the code is regenerated.
|
||||
' </auto-generated>
|
||||
'------------------------------------------------------------------------------
|
||||
|
||||
Option Strict On
|
||||
Option Explicit On
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<MySubMain>false</MySubMain>
|
||||
<SingleInstance>false</SingleInstance>
|
||||
<ShutdownMode>0</ShutdownMode>
|
||||
<EnableVisualStyles>true</EnableVisualStyles>
|
||||
<AuthenticationMode>0</AuthenticationMode>
|
||||
<ApplicationType>2</ApplicationType>
|
||||
<SaveMySettingsOnExit>true</SaveMySettingsOnExit>
|
||||
</MyApplicationData>
|
||||
@@ -0,0 +1,35 @@
|
||||
Imports System
|
||||
Imports System.Reflection
|
||||
Imports System.Runtime.InteropServices
|
||||
|
||||
' General Information about an assembly is controlled through the following
|
||||
' set of attributes. Change these attribute values to modify the information
|
||||
' associated with an assembly.
|
||||
|
||||
' Review the values of the assembly attributes
|
||||
|
||||
<Assembly: AssemblyTitle("TestDataSheetUploader")>
|
||||
<Assembly: AssemblyDescription("")>
|
||||
<Assembly: AssemblyCompany("Hewlett-Packard")>
|
||||
<Assembly: AssemblyProduct("TestDataSheetUploader")>
|
||||
<Assembly: AssemblyCopyright("Copyright © Hewlett-Packard 2016")>
|
||||
<Assembly: AssemblyTrademark("")>
|
||||
|
||||
<Assembly: ComVisible(False)>
|
||||
|
||||
'The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
<Assembly: Guid("7fe555fe-f768-41e5-b89d-89289692ba0e")>
|
||||
|
||||
' Version information for an assembly consists of the following four values:
|
||||
'
|
||||
' Major Version
|
||||
' Minor Version
|
||||
' Build Number
|
||||
' Revision
|
||||
'
|
||||
' You can specify all the values or you can default the Build and Revision Numbers
|
||||
' by using the '*' as shown below:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("1.0.0.0")>
|
||||
<Assembly: AssemblyFileVersion("1.0.0.0")>
|
||||
63
Test Datasheets/TestDataSheetUploader/My Project/Resources.Designer.vb
generated
Normal file
63
Test Datasheets/TestDataSheetUploader/My Project/Resources.Designer.vb
generated
Normal file
@@ -0,0 +1,63 @@
|
||||
'------------------------------------------------------------------------------
|
||||
' <auto-generated>
|
||||
' This code was generated by a tool.
|
||||
' Runtime Version:4.0.30319.42000
|
||||
'
|
||||
' Changes to this file may cause incorrect behavior and will be lost if
|
||||
' the code is regenerated.
|
||||
' </auto-generated>
|
||||
'------------------------------------------------------------------------------
|
||||
|
||||
Option Strict On
|
||||
Option Explicit On
|
||||
|
||||
Imports System
|
||||
|
||||
Namespace My.Resources
|
||||
|
||||
'This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
'class via a tool like ResGen or Visual Studio.
|
||||
'To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
'with the /str option, or rebuild your VS project.
|
||||
'''<summary>
|
||||
''' A strongly-typed resource class, for looking up localized strings, etc.
|
||||
'''</summary>
|
||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0"), _
|
||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
|
||||
Friend Module Resources
|
||||
|
||||
Private resourceMan As Global.System.Resources.ResourceManager
|
||||
|
||||
Private resourceCulture As Global.System.Globalization.CultureInfo
|
||||
|
||||
'''<summary>
|
||||
''' Returns the cached ResourceManager instance used by this class.
|
||||
'''</summary>
|
||||
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
|
||||
Get
|
||||
If Object.ReferenceEquals(resourceMan, Nothing) Then
|
||||
Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("TestDataSheetUploader.Resources", GetType(Resources).Assembly)
|
||||
resourceMan = temp
|
||||
End If
|
||||
Return resourceMan
|
||||
End Get
|
||||
End Property
|
||||
|
||||
'''<summary>
|
||||
''' Overrides the current thread's CurrentUICulture property for all
|
||||
''' resource lookups using this strongly typed resource class.
|
||||
'''</summary>
|
||||
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Friend Property Culture() As Global.System.Globalization.CultureInfo
|
||||
Get
|
||||
Return resourceCulture
|
||||
End Get
|
||||
Set
|
||||
resourceCulture = value
|
||||
End Set
|
||||
End Property
|
||||
End Module
|
||||
End Namespace
|
||||
117
Test Datasheets/TestDataSheetUploader/My Project/Resources.resx
Normal file
117
Test Datasheets/TestDataSheetUploader/My Project/Resources.resx
Normal file
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
73
Test Datasheets/TestDataSheetUploader/My Project/Settings.Designer.vb
generated
Normal file
73
Test Datasheets/TestDataSheetUploader/My Project/Settings.Designer.vb
generated
Normal file
@@ -0,0 +1,73 @@
|
||||
'------------------------------------------------------------------------------
|
||||
' <auto-generated>
|
||||
' This code was generated by a tool.
|
||||
' Runtime Version:4.0.30319.42000
|
||||
'
|
||||
' Changes to this file may cause incorrect behavior and will be lost if
|
||||
' the code is regenerated.
|
||||
' </auto-generated>
|
||||
'------------------------------------------------------------------------------
|
||||
|
||||
Option Strict On
|
||||
Option Explicit On
|
||||
|
||||
|
||||
Namespace My
|
||||
|
||||
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0"), _
|
||||
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Partial Friend NotInheritable Class MySettings
|
||||
Inherits Global.System.Configuration.ApplicationSettingsBase
|
||||
|
||||
Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings)
|
||||
|
||||
#Region "My.Settings Auto-Save Functionality"
|
||||
#If _MyType = "WindowsForms" Then
|
||||
Private Shared addedHandler As Boolean
|
||||
|
||||
Private Shared addedHandlerLockObject As New Object
|
||||
|
||||
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs)
|
||||
If My.Application.SaveMySettingsOnExit Then
|
||||
My.Settings.Save()
|
||||
End If
|
||||
End Sub
|
||||
#End If
|
||||
#End Region
|
||||
|
||||
Public Shared ReadOnly Property [Default]() As MySettings
|
||||
Get
|
||||
|
||||
#If _MyType = "WindowsForms" Then
|
||||
If Not addedHandler Then
|
||||
SyncLock addedHandlerLockObject
|
||||
If Not addedHandler Then
|
||||
AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings
|
||||
addedHandler = True
|
||||
End If
|
||||
End SyncLock
|
||||
End If
|
||||
#End If
|
||||
Return defaultInstance
|
||||
End Get
|
||||
End Property
|
||||
End Class
|
||||
End Namespace
|
||||
|
||||
Namespace My
|
||||
|
||||
<Global.Microsoft.VisualBasic.HideModuleNameAttribute(), _
|
||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute()> _
|
||||
Friend Module MySettingsProperty
|
||||
|
||||
<Global.System.ComponentModel.Design.HelpKeywordAttribute("My.Settings")> _
|
||||
Friend ReadOnly Property Settings() As Global.TestDataSheetUploader.My.MySettings
|
||||
Get
|
||||
Return Global.TestDataSheetUploader.My.MySettings.Default
|
||||
End Get
|
||||
End Property
|
||||
End Module
|
||||
End Namespace
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" UseMySettingsClassName="true">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "TestDataSheetUploader", "TestDataSheetUploader\TestDataSheetUploader.vbproj", "{78941EA8-4EF5-4194-99CD-A08CBB7B52FB}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{78941EA8-4EF5-4194-99CD-A08CBB7B52FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{78941EA8-4EF5-4194-99CD-A08CBB7B52FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{78941EA8-4EF5-4194-99CD-A08CBB7B52FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{78941EA8-4EF5-4194-99CD-A08CBB7B52FB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{78941EA8-4EF5-4194-99CD-A08CBB7B52FB}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<StartupObject>TestDataSheetUploader.Module1</StartupObject>
|
||||
<RootNamespace>TestDataSheetUploader</RootNamespace>
|
||||
<AssemblyName>TestDataSheetUploader</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<MyType>Console</MyType>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<DefineDebug>true</DefineDebug>
|
||||
<DefineTrace>true</DefineTrace>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DocumentationFile>TestDataSheetUploader.xml</DocumentationFile>
|
||||
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<DefineDebug>false</DefineDebug>
|
||||
<DefineTrace>true</DefineTrace>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DocumentationFile>TestDataSheetUploader.xml</DocumentationFile>
|
||||
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OptionExplicit>On</OptionExplicit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OptionCompare>Binary</OptionCompare>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OptionStrict>Off</OptionStrict>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OptionInfer>On</OptionInfer>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Import Include="Microsoft.VisualBasic" />
|
||||
<Import Include="System" />
|
||||
<Import Include="System.Collections" />
|
||||
<Import Include="System.Collections.Generic" />
|
||||
<Import Include="System.Data" />
|
||||
<Import Include="System.Diagnostics" />
|
||||
<Import Include="System.Linq" />
|
||||
<Import Include="System.Xml.Linq" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="HTTPUploader.vb" />
|
||||
<Compile Include="Module1.vb" />
|
||||
<Compile Include="My Project\AssemblyInfo.vb" />
|
||||
<Compile Include="My Project\Application.Designer.vb">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Application.myapp</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="My Project\Resources.Designer.vb">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="My Project\Settings.Designer.vb">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<Compile Include="XMLData.vb" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="My Project\Resources.resx">
|
||||
<Generator>VbMyResourcesResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.vb</LastGenOutput>
|
||||
<CustomToolNamespace>My.Resources</CustomToolNamespace>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="My Project\Application.myapp">
|
||||
<Generator>MyApplicationCodeGenerator</Generator>
|
||||
<LastGenOutput>Application.Designer.vb</LastGenOutput>
|
||||
</None>
|
||||
<None Include="My Project\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<CustomToolNamespace>My</CustomToolNamespace>
|
||||
<LastGenOutput>Settings.Designer.vb</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
81
Test Datasheets/TestDataSheetUploader/XMLData.vb
Normal file
81
Test Datasheets/TestDataSheetUploader/XMLData.vb
Normal file
@@ -0,0 +1,81 @@
|
||||
Imports System.Xml
|
||||
Imports System.Net
|
||||
Imports System.IO
|
||||
|
||||
Namespace CSFramework_Utilities
|
||||
|
||||
Public Class XMLData
|
||||
|
||||
Public Shared Function XMLStringFromDataset(ByVal ds As DataSet) As String
|
||||
Dim sw As New StringWriter()
|
||||
ds.WriteXml(sw, XmlWriteMode.IgnoreSchema)
|
||||
Return sw.ToString()
|
||||
End Function
|
||||
|
||||
Public Shared Function DownloadXMLAsDataset(ByVal url As String, Optional ByVal credentials As Net.NetworkCredential = Nothing) As DataSet
|
||||
|
||||
Dim myXMLReader As XmlReader
|
||||
Dim myDataSet As New DataSet
|
||||
If credentials IsNot Nothing Then
|
||||
Dim myXMLResolver As XmlUrlResolver = New XmlUrlResolver
|
||||
myXMLResolver.Credentials = credentials
|
||||
Dim myXMLSettings As XmlReaderSettings = New XmlReaderSettings
|
||||
myXMLSettings.XmlResolver = myXMLResolver
|
||||
myXMLReader = XmlReader.Create(url, myXMLSettings)
|
||||
Else
|
||||
myXMLReader = XmlReader.Create(url)
|
||||
End If
|
||||
myDataSet.ReadXml(myXMLReader)
|
||||
Return myDataSet
|
||||
End Function
|
||||
|
||||
|
||||
Public Shared Function DownloadXMLWithDatasetPost(ByVal url As String, ByVal datasetToPost As DataSet, ByVal credentials As System.Net.NetworkCredential) As String
|
||||
|
||||
|
||||
Dim xmlrequest As HttpWebRequest = WebRequest.Create(url)
|
||||
xmlrequest.ContentType = "text/xml"
|
||||
xmlrequest.Method = WebRequestMethods.Http.Post
|
||||
xmlrequest.Credentials = credentials
|
||||
xmlrequest.Timeout = 2000000
|
||||
Try
|
||||
|
||||
Dim newStream As Stream = xmlrequest.GetRequestStream()
|
||||
datasetToPost.WriteXml(newStream)
|
||||
newStream.Close()
|
||||
|
||||
Dim xmlresponse As WebResponse = xmlrequest.GetResponse()
|
||||
Dim responseStr As String = ConvertStreamToString(xmlresponse.GetResponseStream)
|
||||
|
||||
|
||||
Return responseStr
|
||||
|
||||
Catch ex As Exception
|
||||
Return "DownloadXMLWithDatasetPost ERROR: " & vbCrLf & ex.ToString
|
||||
End Try
|
||||
|
||||
End Function
|
||||
|
||||
Public Shared Function ConvertStreamToString(ByVal InputStream As System.IO.Stream) As String
|
||||
Dim sr As System.IO.StreamReader = New System.IO.StreamReader(InputStream)
|
||||
Dim responseStr As String = sr.ReadToEnd()
|
||||
Return responseStr
|
||||
End Function
|
||||
|
||||
Public Shared Function DatasetFromXML(ByVal xml As String) As DataSet
|
||||
|
||||
Dim dataSet As DataSet = New DataSet
|
||||
|
||||
|
||||
Dim xmlSR As System.IO.StringReader = New System.IO.StringReader(xml)
|
||||
|
||||
dataSet.ReadXml(xmlSR)
|
||||
|
||||
Return dataSet
|
||||
|
||||
End Function
|
||||
|
||||
|
||||
End Class
|
||||
|
||||
End Namespace
|
||||
40
Test Datasheets/TestDataSheetUploader/app.config
Normal file
40
Test Datasheets/TestDataSheetUploader/app.config
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="UploaderServiceURL" value="https://www.dataforth.com/Services/Uploader.aspx"/>
|
||||
<add key="DirectoryManifestServiceURL" value="https://www.dataforth.com/Services/DirectoryManifest.aspx"/>
|
||||
<add key="DeleteFileServiceURL" value="https://www.dataforth.com/Services/DeleteFile.aspx"/>
|
||||
<add key="ServiceUsername" value="DataforthWebShare"/>
|
||||
<add key="ServicePassword" value="Data6277"/>
|
||||
|
||||
<add key="TestDataSheetPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||
<add key="TestFolderPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||
|
||||
<add key="InventoryDataStagingFolder" value="C:\TestDataSheetUploader\staging"/>
|
||||
<add key="InventoryDataSourceFolder" value="C:\TestDataSheetUploader\src"/>
|
||||
<add key="InventoryDataFiles" value="AvSelCat.csv,AvSelCus.csv"/>
|
||||
|
||||
<add key="TestMode" value="false"/>
|
||||
|
||||
</appSettings>
|
||||
<system.diagnostics>
|
||||
<sources>
|
||||
<!-- This section defines the logging configuration for My.Application.Log -->
|
||||
<source name="DefaultSource" switchName="DefaultSwitch">
|
||||
<listeners>
|
||||
<add name="FileLog"/>
|
||||
<!-- Uncomment the below section to write to the Application Event Log -->
|
||||
<!--<add name="EventLog"/>-->
|
||||
</listeners>
|
||||
</source>
|
||||
</sources>
|
||||
<switches>
|
||||
<add name="DefaultSwitch" value="Information"/>
|
||||
</switches>
|
||||
<sharedListeners>
|
||||
<add name="FileLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" initializeData="FileLogWriter"/>
|
||||
<!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log -->
|
||||
<!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
|
||||
</sharedListeners>
|
||||
</system.diagnostics>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup></configuration>
|
||||
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="UploaderServiceURL" value="https://www.dataforth.com/Services/Uploader.aspx"/>
|
||||
<add key="DirectoryManifestServiceURL" value="https://www.dataforth.com/Services/DirectoryManifest.aspx"/>
|
||||
<add key="DeleteFileServiceURL" value="https://www.dataforth.com/Services/DeleteFile.aspx"/>
|
||||
<add key="ServiceUsername" value="DataforthWebShare"/>
|
||||
<add key="ServicePassword" value="Data6277"/>
|
||||
|
||||
<add key="TestDataSheetPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||
<add key="TestFolderPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||
|
||||
<add key="InventoryDataStagingFolder" value="C:\TestDataSheetUploader\staging"/>
|
||||
<add key="InventoryDataSourceFolder" value="C:\TestDataSheetUploader\src"/>
|
||||
<add key="InventoryDataFiles" value="AvSelCat.csv,AvSelCus.csv"/>
|
||||
|
||||
<add key="TestMode" value="false"/>
|
||||
|
||||
</appSettings>
|
||||
<system.diagnostics>
|
||||
<sources>
|
||||
<!-- This section defines the logging configuration for My.Application.Log -->
|
||||
<source name="DefaultSource" switchName="DefaultSwitch">
|
||||
<listeners>
|
||||
<add name="FileLog"/>
|
||||
<!-- Uncomment the below section to write to the Application Event Log -->
|
||||
<!--<add name="EventLog"/>-->
|
||||
</listeners>
|
||||
</source>
|
||||
</sources>
|
||||
<switches>
|
||||
<add name="DefaultSwitch" value="Information"/>
|
||||
</switches>
|
||||
<sharedListeners>
|
||||
<add name="FileLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" initializeData="FileLogWriter"/>
|
||||
<!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log -->
|
||||
<!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
|
||||
</sharedListeners>
|
||||
</system.diagnostics>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup></configuration>
|
||||
Binary file not shown.
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="UploaderServiceURL" value="https://www.dataforth.com/Services/Uploader.aspx"/>
|
||||
<add key="DirectoryManifestServiceURL" value="https://www.dataforth.com/Services/DirectoryManifest.aspx"/>
|
||||
<add key="DeleteFileServiceURL" value="https://www.dataforth.com/Services/DeleteFile.aspx"/>
|
||||
<add key="ServiceUsername" value="DataforthWebShare"/>
|
||||
<add key="ServicePassword" value="Data6277"/>
|
||||
|
||||
<add key="TestDataSheetPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||
<add key="TestFolderPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||
|
||||
<add key="InventoryDataStagingFolder" value="C:\TestDataSheetUploader\staging"/>
|
||||
<add key="InventoryDataSourceFolder" value="C:\TestDataSheetUploader\src"/>
|
||||
<add key="InventoryDataFiles" value="AvSelCat.csv,AvSelCus.csv"/>
|
||||
|
||||
<add key="TestMode" value="false"/>
|
||||
|
||||
</appSettings>
|
||||
<system.diagnostics>
|
||||
<sources>
|
||||
<!-- This section defines the logging configuration for My.Application.Log -->
|
||||
<source name="DefaultSource" switchName="DefaultSwitch">
|
||||
<listeners>
|
||||
<add name="FileLog"/>
|
||||
<!-- Uncomment the below section to write to the Application Event Log -->
|
||||
<!--<add name="EventLog"/>-->
|
||||
</listeners>
|
||||
</source>
|
||||
</sources>
|
||||
<switches>
|
||||
<add name="DefaultSwitch" value="Information"/>
|
||||
</switches>
|
||||
<sharedListeners>
|
||||
<add name="FileLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" initializeData="FileLogWriter"/>
|
||||
<!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log -->
|
||||
<!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
|
||||
</sharedListeners>
|
||||
</system.diagnostics>
|
||||
<startup><supportedRuntime version="v2.0.50727"/></startup></configuration>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>
|
||||
TestDataSheetUploader
|
||||
</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:TestDataSheetUploader.My.Resources.Resources">
|
||||
<summary>
|
||||
A strongly-typed resource class, for looking up localized strings, etc.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:TestDataSheetUploader.My.Resources.Resources.ResourceManager">
|
||||
<summary>
|
||||
Returns the cached ResourceManager instance used by this class.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:TestDataSheetUploader.My.Resources.Resources.Culture">
|
||||
<summary>
|
||||
Overrides the current thread's CurrentUICulture property for all
|
||||
resource lookups using this strongly typed resource class.
|
||||
</summary>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
477923
Test Datasheets/TestDataSheetUploader/bin/Debug/manifest.xml
Normal file
477923
Test Datasheets/TestDataSheetUploader/bin/Debug/manifest.xml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
08/22/YYYY 15:47:17 | SyncFolder(TestFolder) started.
|
||||
08/22/YYYY 15:47:32 | Upload FAILED for C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists\Custom Product Listing.pdf
|
||||
08/22/YYYY 15:47:32 | Upload FAIL MESSAGE: GSSG Service Upload Error: UploadType not recognized: TestFolder
|
||||
08/22/YYYY 15:47:32 | Upload FAILED for C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists\Custom Product Rules.pdf
|
||||
08/22/YYYY 15:47:32 | Upload FAIL MESSAGE: GSSG Service Upload Error: UploadType not recognized: TestFolder
|
||||
08/22/YYYY 15:47:32 | No obsolete TestFolder files were detected.
|
||||
@@ -0,0 +1,6 @@
|
||||
08/22/YYYY 15:51:12 | SyncFolder(TestFolder) started.
|
||||
08/22/YYYY 15:51:15 | Upload FAILED for C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists\Custom Product Listing.pdf
|
||||
08/22/YYYY 15:51:15 | Upload FAIL MESSAGE: Dataforth Service Upload Error: Access to the path 'C:\inetpub\wwwroot\dataforth.com\WebShare\ProcessCheckOutTestFolder\Custom Product Listing.pdf' is denied.
|
||||
08/22/YYYY 15:51:15 | Upload FAILED for C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists\Custom Product Rules.pdf
|
||||
08/22/YYYY 15:51:15 | Upload FAIL MESSAGE: Dataforth Service Upload Error: Access to the path 'C:\inetpub\wwwroot\dataforth.com\WebShare\ProcessCheckOutTestFolder\Custom Product Rules.pdf' is denied.
|
||||
08/22/YYYY 15:51:15 | No obsolete TestFolder files were detected.
|
||||
@@ -0,0 +1,4 @@
|
||||
08/22/YYYY 15:57:38 | SyncFolder(TestFolder) started.
|
||||
08/22/YYYY 15:57:39 | Uploaded file: C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists\Custom Product Listing.pdf
|
||||
08/22/YYYY 15:57:40 | Uploaded file: C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists\Custom Product Rules.pdf
|
||||
08/22/YYYY 15:57:40 | No obsolete TestFolder files were detected.
|
||||
@@ -0,0 +1,9 @@
|
||||
08/22/YYYY 16:00:07 | SyncFolder(TestDataSheet) started.
|
||||
08/22/YYYY 16:02:13 | Exception in SyncFolder: System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.
|
||||
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
|
||||
at System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace()
|
||||
at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
|
||||
at System.Xml.XmlReader.MoveToContent()
|
||||
at System.Data.DataSet.ReadXml(XmlReader reader, Boolean denyResolving)
|
||||
at CSFramework.CSFramework_Utilities.XMLData.DatasetFromXML(String xml) in C:\Users\hoffm\Documents\Visual Studio 2015\Projects\OEMData\CSFramework\CSFramework\CSFramework_Utilities\XMLData.vb:line 66
|
||||
at TestDataSheetUploader.Module1.SyncFolder(String FolderAlias) in C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\Module1.vb:line 81
|
||||
@@ -0,0 +1,8 @@
|
||||
03/31/YYYY 16:13:55 | SyncFolder(InventoryDataFolder) started.
|
||||
03/31/YYYY 16:14:00 | Exception in SyncFolder: System.Xml.XmlException: Root element is missing.
|
||||
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
|
||||
at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
|
||||
at System.Xml.XmlReader.MoveToContent()
|
||||
at System.Data.DataSet.ReadXml(XmlReader reader, Boolean denyResolving)
|
||||
at TestDataSheetUploader.CSFramework_Utilities.XMLData.DatasetFromXML(String xml) in C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\XMLData.vb:line 72
|
||||
at TestDataSheetUploader.Module1.SyncFolder(String FolderAlias) in C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\Module1.vb:line 112
|
||||
@@ -0,0 +1,3 @@
|
||||
03/31/YYYY 16:18:48 | SyncFolder(InventoryDataFolder) started.
|
||||
03/31/YYYY 16:19:34 | Exception in SyncFolder: System.NullReferenceException: Object reference not set to an instance of an object.
|
||||
at TestDataSheetUploader.Module1.SyncFolder(String FolderAlias) in C:\Users\hoffm\Documents\Visual Studio 2015\Projects\Dataforth\TestDataSheetUploader\TestDataSheetUploader\Module1.vb:line 114
|
||||
@@ -0,0 +1,9 @@
|
||||
03/31/YYYY 16:20:24 | SyncFolder(InventoryDataFolder) started.
|
||||
03/31/YYYY 16:20:30 | Manifest downloaded with 1 files.
|
||||
03/31/YYYY 16:20:30 | Accessing local folder: C:\TestDataSheetUploader\staging
|
||||
03/31/YYYY 16:20:30 | Found at least 1 file in local folder
|
||||
03/31/YYYY 16:20:30 | Requesting upload: AvSelCat.csv
|
||||
03/31/YYYY 16:20:30 | Requesting upload: AvSelCus.csv
|
||||
03/31/YYYY 16:20:30 | Found 2 files that need to be uploaded.
|
||||
03/31/YYYY 16:20:41 | Requested InventoryDataFolder Delete: New Text Document.txt
|
||||
03/31/YYYY 16:20:41 | Found 1 files to delete.
|
||||
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="UploaderServiceURL" value="https://www.dataforth.com/Services/Uploader.aspx"/>
|
||||
<add key="DirectoryManifestServiceURL" value="https://www.dataforth.com/Services/DirectoryManifest.aspx"/>
|
||||
<add key="DeleteFileServiceURL" value="https://www.dataforth.com/Services/DeleteFile.aspx"/>
|
||||
<add key="ServiceUsername" value="DataforthWebShare"/>
|
||||
<add key="ServicePassword" value="Data6277"/>
|
||||
|
||||
<add key="TestDataSheetPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||
<add key="TestFolderPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||
|
||||
<add key="InventoryDataStagingFolder" value="C:\TestDataSheetUploader\staging"/>
|
||||
<add key="InventoryDataSourceFolder" value="C:\TestDataSheetUploader\src"/>
|
||||
<add key="InventoryDataFiles" value="AvSelCat.csv,AvSelCus.csv"/>
|
||||
|
||||
<add key="TestMode" value="false"/>
|
||||
|
||||
</appSettings>
|
||||
<system.diagnostics>
|
||||
<sources>
|
||||
<!-- This section defines the logging configuration for My.Application.Log -->
|
||||
<source name="DefaultSource" switchName="DefaultSwitch">
|
||||
<listeners>
|
||||
<add name="FileLog"/>
|
||||
<!-- Uncomment the below section to write to the Application Event Log -->
|
||||
<!--<add name="EventLog"/>-->
|
||||
</listeners>
|
||||
</source>
|
||||
</sources>
|
||||
<switches>
|
||||
<add name="DefaultSwitch" value="Information"/>
|
||||
</switches>
|
||||
<sharedListeners>
|
||||
<add name="FileLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" initializeData="FileLogWriter"/>
|
||||
<!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log -->
|
||||
<!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
|
||||
</sharedListeners>
|
||||
</system.diagnostics>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup></configuration>
|
||||
Binary file not shown.
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="UploaderServiceURL" value="https://www.dataforth.com/Services/Uploader.aspx"/>
|
||||
<add key="DirectoryManifestServiceURL" value="https://www.dataforth.com/Services/DirectoryManifest.aspx"/>
|
||||
<add key="DeleteFileServiceURL" value="https://www.dataforth.com/Services/DeleteFile.aspx"/>
|
||||
<add key="ServiceUsername" value="DataforthWebShare"/>
|
||||
<add key="ServicePassword" value="Data6277"/>
|
||||
|
||||
<add key="TestDataSheetPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||
<add key="TestFolderPath" value="C:\Users\hoffm\Documents\Customer Folders\Dataforth\product lists"/>
|
||||
|
||||
<add key="InventoryDataStagingFolder" value="C:\TestDataSheetUploader\staging"/>
|
||||
<add key="InventoryDataSourceFolder" value="C:\TestDataSheetUploader\src"/>
|
||||
<add key="InventoryDataFiles" value="AvSelCat.csv,AvSelCus.csv"/>
|
||||
|
||||
<add key="TestMode" value="false"/>
|
||||
|
||||
</appSettings>
|
||||
<system.diagnostics>
|
||||
<sources>
|
||||
<!-- This section defines the logging configuration for My.Application.Log -->
|
||||
<source name="DefaultSource" switchName="DefaultSwitch">
|
||||
<listeners>
|
||||
<add name="FileLog"/>
|
||||
<!-- Uncomment the below section to write to the Application Event Log -->
|
||||
<!--<add name="EventLog"/>-->
|
||||
</listeners>
|
||||
</source>
|
||||
</sources>
|
||||
<switches>
|
||||
<add name="DefaultSwitch" value="Information"/>
|
||||
</switches>
|
||||
<sharedListeners>
|
||||
<add name="FileLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" initializeData="FileLogWriter"/>
|
||||
<!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log -->
|
||||
<!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
|
||||
</sharedListeners>
|
||||
</system.diagnostics>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup></configuration>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0"?>
|
||||
<doc>
|
||||
<assembly>
|
||||
<name>
|
||||
TestDataSheetUploader
|
||||
</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:TestDataSheetUploader.My.Resources.Resources">
|
||||
<summary>
|
||||
A strongly-typed resource class, for looking up localized strings, etc.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:TestDataSheetUploader.My.Resources.Resources.ResourceManager">
|
||||
<summary>
|
||||
Returns the cached ResourceManager instance used by this class.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:TestDataSheetUploader.My.Resources.Resources.Culture">
|
||||
<summary>
|
||||
Overrides the current thread's CurrentUICulture property for all
|
||||
resource lookups using this strongly typed resource class.
|
||||
</summary>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user