| # atris.md — A new system for an AI agent team | ||
| > **Drop this markdown file anywhere. Scaffold and operate an AI agent team.** | ||
| This spec defines how to transform any system (codebase, product, sales process, research) into a self-documenting, AI-navigable workspace. Standard structure: `atris/` folder with MAP.md, team/, and TODO.md. | ||
| **Workflow:** Daily logs → Navigator plans → Executor builds → Validator reviews. | ||
| --- | ||
| ## Phase 1: Generate MAP.md (Universal Navigation) | ||
| **Goal:** Create a single-source-of-truth navigation guide that agents reference for all system/architecture questions. | ||
| **Why This Matters:** | ||
| - Agents waste time re-learning system structure on each task | ||
| - MAP.md eliminates friction—one grep-friendly index that's always accurate | ||
| - All agents reference the same truth, preventing contradictory guidance | ||
| - Works for ANY domain: code, product, sales, research, operations | ||
| **Agent Instructions:** | ||
| 1. **Scan the project root** (ignore: `node_modules/`, `.git/`, `dist/`, `build/`, `.DS_Store`, `*.log`) | ||
| 2. **For each major directory** (depth 1-2 levels), extract: | ||
| - Purpose (1 sentence: why does this directory exist?) | ||
| - Key files with line-count ranges (e.g., `auth.ts: 200 lines`) | ||
| - Search accelerators (ripgrep patterns for fast navigation) | ||
| 3. **Create `/atris/MAP.md`** with ONLY these sections (no extras): | ||
| - **Quick Reference Index** (top) — Grep-friendly shortcuts (e.g., `CHAT:BACKEND -> rg -n "def quick_chat" backend/`) | ||
| - **By-Feature** — Chat, files, auth, billing, etc. (answer: "where is feature X?") | ||
| - **By-Concern** — State management, API layer, UI system, etc. (answer: "where is concern Y?") | ||
| - **Critical Files** — Files >10KB or >100 lines of logic = high-impact (mark as ⭐) | ||
| - **Entry Points** — 3-5 entry points clearly marked (landing page, dashboard, API routes, etc.) | ||
| 4. **DO NOT include this:** | ||
| - COMPLEX Architecture Flows unless specified (keep it simple to understand) | ||
| - TODOs/Improvements (those go in TODO.md) | ||
| - Project stats (unnecessary metadata) | ||
| 5. **Quality Checklist Before Outputting:** | ||
| - [ ] Does every major file/component have a one-liner explaining its purpose? | ||
| - [ ] Can a new person answer "where is X?" in <30 seconds using this map? | ||
| 6. **Output:** `/atris/MAP.md` (target: 300-500 lines for large systems; scale to project size) | ||
| 7. **After MAP.md generation:** Append lightweight project context to agent templates | ||
| - Add `## Project Context` section to each agent (navigator, executor, validator) | ||
| - Include: framework, 3-5 key directories, 3-5 search accelerators | ||
| - Keep it minimal (5-10 lines max per agent) - avoid bloat | ||
| - Format: | ||
| ```markdown | ||
| --- | ||
| ## Project Context (Auto-generated from MAP.md) | ||
| - **Framework:** Next.js 14 | ||
| - **Key dirs:** app/, components/, lib/ | ||
| - **Search patterns:** | ||
| - Components: `rg "export default" components/` | ||
| - API routes: `rg "export async function" app/api/` | ||
| ``` | ||
| --- | ||
| ## Phase 2: Foundational Agent Templates | ||
| Atris ships with pre-built agent templates in `/atris/team/` (copied during `atris init`). These templates provide battle-tested specs that work out of the box. Each agent has explicit guardrails. | ||
| **Templates included:** | ||
| ### Agent 1: **navigator.md** (in `/atris/team/`) | ||
| - **Role:** System Navigator & Architecture Expert | ||
| - **Activation Prompt:** | ||
| ``` | ||
| You are the system navigator. Your sole job is answering "where is X?" with precision. | ||
| Rules: | ||
| 1. ALWAYS start with: "According to MAP.md, [item] is located in..." | ||
| 2. ALWAYS cite file:line or component references (e.g., `app/auth/middleware.ts:15-45`) | ||
| 3. Explain flows end-to-end (frontend → backend → database, or research → analysis → writeup) | ||
| 4. Identify coupling points and structure violations | ||
| 5. Guide people to the right location in <5 clicks | ||
| DO NOT: | ||
| - Execute changes or modifications without explicit approval | ||
| - Make architecture/structure decisions without approval | ||
| - Assume locations; always reference MAP.md | ||
| ``` | ||
| - **Knowledge Base:** MAP.md, architecture docs, specs, design docs | ||
| - **Success Metric:** Every question answered with exact references, zero guesses | ||
| ### Agent 2: **executor.md** (in `/atris/team/`) | ||
| - **Role:** Context-Aware Task Executor | ||
| - **Activation Prompt:** | ||
| ``` | ||
| You are the task executor. When given a task, extract exact context and execute step-by-step. | ||
| Rules: | ||
| 1. Read MAP.md first; extract file:line references for all related files | ||
| 2. Identify ALL files that will be touched (use ripgrep patterns from MAP) | ||
| 3. Map dependencies and risk zones | ||
| 4. Create a concise 4-5 sentence execution plan with: | ||
| - File paths | ||
| - Line numbers for modifications | ||
| - Exact description of changes | ||
| 5. Execute step-by-step, validating at each stage | ||
| Format: "Task: [name] | Files: [path:line] | Changes: [exact description]" | ||
| DO NOT: | ||
| - Skip validation steps | ||
| - Modify files outside the planned scope | ||
| - Ignore type errors or test failures | ||
| ``` | ||
| - **Knowledge Base:** MAP.md, TODO.md (generated), test suite, type definitions | ||
| - **Success Metric:** Tasks completed 95% first-try with zero regressions | ||
| ### Agent 3: **validator.md** (in `/atris/team/`) | ||
| - **Role:** Quality Gatekeeper | ||
| - **Activation Prompt:** | ||
| ``` | ||
| You are the validator. After ANY change, verify safety and accuracy. | ||
| Rules: | ||
| 1. Run type-check, lint, tests automatically | ||
| 2. Verify all file references in MAP.md still exist and are accurate | ||
| 3. Update MAP.md if architecture changed | ||
| 4. Check for breaking changes or coupling violations | ||
| 5. Report: "✓ Safe to merge" or "⚠ Risks: [list]" | ||
| ALWAYS cite MAP.md and explain why changes are safe/risky. | ||
| DO NOT: | ||
| - Approve changes without running tests | ||
| - Allow breaking changes silently | ||
| - Update MAP.md without explaining what changed | ||
| ``` | ||
| - **Knowledge Base:** MAP.md, test suite, type definitions, architecture principles | ||
| - **Success Metric:** Zero undetected breaking changes reach production | ||
| --- | ||
| ## Phase 3: Task Context System (TODO.md in `/atris/`, formerly `TODO.md`) | ||
| **Goal:** Automatic task extraction with exact file/component context, so agents never guess. | ||
| **Generated File Format:** | ||
| ```markdown | ||
| # Task Contexts — Auto-extracted from MAP.md | ||
| ## Task Template | ||
| - **Task ID:** T-[AUTO] | ||
| - **Name:** [Feature/Fix Name] | ||
| - **Complexity:** [Trivial|Simple|Moderate|Complex|Epic] | ||
| - Trivial: Single-line fix, typo, comment | ||
| - Simple: 1-2 files, <50 lines, no cross-module deps | ||
| - Moderate: 3-5 files, <200 lines, some deps | ||
| - Complex: 5+ files, >200 lines, multiple systems | ||
| - Epic: Architectural change, multi-system refactor | ||
| - **Scope:** | ||
| - Files touched: [count] | ||
| - Lines affected: ~[estimate] | ||
| - Dependencies: [count of related files/modules] | ||
| - **Context Files:** [file:line_start-line_end] (from MAP critical files) | ||
| - **Execution Plan:** | ||
| 1. [Step 1 with file:line reference] | ||
| 2. [Step 2 with file:line reference] | ||
| 3. [Step 3 with file:line reference] | ||
| - **Success Criteria:** [Measurable, testable] | ||
| - **Dependencies:** [Task IDs or external dependencies] | ||
| - **Risk Level:** [Low/Medium/High] | ||
| - Blast radius: [how many systems/endpoints affected] | ||
| - Test coverage: [existing tests? new tests needed?] | ||
| - Rollback: [Easy|Moderate|Difficult] | ||
| ## Example Task (Auto-Generated) | ||
| - **Task ID:** T-001 | ||
| - **Name:** Add authentication to file upload | ||
| - **Complexity:** Simple | ||
| - **Scope:** | ||
| - Files touched: 3 | ||
| - Lines affected: ~20 | ||
| - Dependencies: 1 (auth middleware) | ||
| - **Context Files:** | ||
| - `app/api/files/upload/route.ts:1-50` (handler) | ||
| - `app/auth/middleware.ts:15-45` (auth check) | ||
| - `types/auth.ts:8-20` (auth types) | ||
| - **Execution Plan:** | ||
| 1. Add `verifySession()` call to upload handler (line 20) | ||
| 2. Return 401 if no session (add lines 21-23) | ||
| 3. Add auth test to `__tests__/upload.test.ts:112-125` | ||
| 4. Run `npm run test` and verify all pass | ||
| - **Success Criteria:** Upload rejects unauthenticated requests; all tests pass; MAP.md updated | ||
| - **Dependencies:** None | ||
| - **Risk Level:** Low | ||
| - Blast radius: Single endpoint (upload only) | ||
| - Test coverage: Existing auth tests; new upload auth test needed | ||
| - Rollback: Easy (single handler change, no DB migration) | ||
| ``` | ||
| **Agent Instructions:** | ||
| 1. After MAP.md is generated, scan for: | ||
| - Incomplete work (TODOs, FIXMEs, gaps marked with line numbers) | ||
| - High-risk areas (>500 lines, multiple dependencies, touching shared state) | ||
| - Cross-component dependencies that could break easily | ||
| 2. Auto-generate 5-10 canonical tasks with exact file:line or component references | ||
| - Include both quick wins (low-risk) and strategic work (high-impact) | ||
| - Map all dependencies explicitly | ||
| 3. Output: `/atris/TODO.md` (maintains and evolves as system changes) | ||
| 4. On each MAP.md update, regenerate TODO.md to reflect new state | ||
| --- | ||
| ## Phase 4: Activation & Handoff | ||
| **After `atris init`, your workspace contains:** | ||
| - ✅ `atris.md` (this spec) | ||
| - ✅ `PERSONA.md` (agent communication style) | ||
| - ✅ `GETTING_STARTED.md` (user guide) | ||
| - ✅ `team/navigator.md` (pre-built template) | ||
| - ✅ `team/executor.md` (pre-built template) | ||
| - ✅ `team/validator.md` (pre-built template) | ||
| - ⏳ `MAP.md` (AI agent generates from codebase) | ||
| - ⏳ `TODO.md` (AI agent generates from MAP) | ||
| **Agent Enhancement:** | ||
| After MAP.md generation, agents receive project context injection (framework, key dirs, search patterns). This keeps base templates clean while adding project-specific accelerators. | ||
| **Agent Behavior Activates Automatically:** | ||
| | Trigger | Agent | Action | | ||
| |---------|-------|--------| | ||
| | "Where is X?" | navigator | Answers with MAP.md:line reference + project patterns | | ||
| | "Do task Y" | executor | Extracts context, plans execution, cites file:line | | ||
| | After change | validator | Checks validity, updates docs, blocks unsafe changes | | ||
| | New agent joins | navigator | Reads MAP.md, immediately productive (no ramp-up) | | ||
| **Validation Checklist:** | ||
| - [ ] All three agents can read and cite MAP.md | ||
| - [ ] navigator answers 5 test questions with exact references | ||
| - [ ] executor completes a sample task without regressions | ||
| - [ ] validator successfully detects and blocks a breaking change | ||
| - [ ] MAP.md is accurate and stays in sync with the system, especially after changes. agents will change. | ||
| --- | ||
| ## Phase 5: Daily Workflow | ||
| **How the System Operates Day-to-Day:** | ||
| 1. **Brain Dump** — Run `atris log`, type thoughts into `## Inbox` section (unfiltered, no structure required) | ||
| 2. **Navigator Reviews** — Processes inbox entries, identifies patterns, creates tasks in TODO.md with MAP.md context | ||
| 3. **Executor Builds** — Takes task → ASCII visualization → get approval → build step-by-step → validate alignment | ||
| 4. **Validator Reviews** — Ultrathinks (3x) → tests → auto-fixes bugs → cleans up (deletes completed tasks, target: 0) → updates MAP.md → moves log to Completed ✅ → extracts lessons | ||
| **Daily Goal:** Inbox zero. All thoughts processed, tasks executed, docs updated. | ||
| --- | ||
| ## Phase 5.1: Journal Protocol v1.0 | ||
| **The Atris Journal is a standardized markdown format that enables:** | ||
| - **Human → Agent coordination** (brain dumps → structured tasks) | ||
| - **Multi-agent coordination** (agents communicate via journal sections) | ||
| - **Markdown → UI rendering** (structured data for kanban, charts, progress bars) | ||
| - **Self-evolution** (journal tracks issues, system fixes itself) | ||
| **Same markdown = CLI readable + UI renderable + agent parsable.** | ||
| --- | ||
| ### Section Semantics | ||
| **Structured Sections** (parsable for UI rendering): | ||
| - **`## Inbox`** — Unfiltered thoughts, ideas, issues. Navigator processes these. | ||
| - **`## Backlog`** — Tasks extracted from Inbox, not yet started. | ||
| - **`## In Progress 🔄`** — Tasks currently being worked on (with `**Claimed by:**` metadata). | ||
| - **`## Completed ✅`** — Finished work with timestamps and learnings. | ||
| **Free-Form Sections** (rich text editors): | ||
| - **`## Notes`** — Session notes, meeting notes, context. | ||
| - **`## Lessons Learned`** — Patterns, insights, reusable knowledge. | ||
| **Metadata Sections**: | ||
| - **`## Timestamps`** — Activity log (optional, for analytics). | ||
| --- | ||
| ### Format Rules (Regex-Friendly) | ||
| **Structured Items** (enables UI parsing): | ||
| **Inbox Items:** | ||
| ``` | ||
| - **I{n}:** Description | ||
| ``` | ||
| - Pattern: `/^- \*\*I(\d+):\*\*\s*(.+)$/` | ||
| - Example: `- **I1:** Add auth to upload endpoint` | ||
| - UI: Renders as cards in inbox view | ||
| **Completed Items:** | ||
| ``` | ||
| - **C{n}:** Description | ||
| ``` | ||
| - Pattern: `/^- \*\*C(\d+):\*\*\s*(.+)$/` | ||
| - Example: `- **C1:** Fixed bidirectional journal sync` | ||
| - UI: Renders in timeline/chart view | ||
| **Tasks:** | ||
| ``` | ||
| - **T{n}:** Description | ||
| ``` | ||
| - Pattern: `/^- \*\*T(\d+):\*\*\s*(.+)$/` | ||
| - Example: `- **T1:** Add Journal Protocol to atris.md` | ||
| - UI: Renders in kanban board (Backlog → In Progress → Completed) | ||
| **Status Metadata:** | ||
| ``` | ||
| **Claimed by:** [Agent/Name] at [Timestamp] | ||
| **Status:** [Status text] | ||
| ``` | ||
| - Pattern: `/\*\*Claimed by:\*\* (.+)/` | ||
| - UI: Renders as progress bars, ownership indicators | ||
| **Free-Form Sections:** | ||
| - No format rules required. Use standard markdown (headings, lists, code blocks, etc.). | ||
| - UI: Renders in rich text editor with full markdown support. | ||
| --- | ||
| ### Markdown → UI Mapping | ||
| **Structured sections → UI components:** | ||
| - **Inbox** → Card grid (each `I{n}` item = card) | ||
| - **Backlog** → Kanban column (each `T{n}` item = card) | ||
| - **In Progress** → Kanban column + progress indicators (`**Claimed by:**` → avatar/badge) | ||
| - **Completed** → Timeline view (each `C{n}` item = timeline entry) | ||
| **Free-form sections → Rich editors:** | ||
| - **Notes** → Markdown editor (WYSIWYG or source) | ||
| - **Lessons Learned** → Markdown editor with syntax highlighting | ||
| **Metadata → UI widgets:** | ||
| - `**Claimed by:**` → User avatar + name badge | ||
| - `**Status:**` → Progress bar or status pill | ||
| **Same file works for:** | ||
| - CLI: `grep`, `cat`, standard text tools | ||
| - Web: Parsed into React components | ||
| - Mobile: Native UI with swipe gestures | ||
| - Agent: Parse via regex, coordinate via section writes | ||
| --- | ||
| ### Agent Coordination Guidelines | ||
| **Multi-agent write behavior:** | ||
| **Navigator Agent:** | ||
| - Reads: `## Inbox` section | ||
| - Writes: `## Backlog` section (creates tasks from inbox items) | ||
| - Writes: `## Notes` section (planning notes, ASCII diagrams) | ||
| **Executor Agent:** | ||
| - Reads: `## Backlog` section | ||
| - Writes: `## In Progress 🔄` section (claims task with `**Claimed by:**`) | ||
| - Writes: `## Completed ✅` section (when done, with timestamps) | ||
| - Writes: `## Notes` section (execution notes, debugging notes) | ||
| **Validator Agent:** | ||
| - Reads: `## Completed ✅` section | ||
| - Writes: `## Lessons Learned` section (extracts patterns) | ||
| - Writes: `## Notes` section (validation results, test outcomes) | ||
| **Launcher Agent:** | ||
| - Reads: `## Completed ✅` section | ||
| - Writes: `## Notes` section (launch summary, learnings) | ||
| - Moves: Inbox items to Completed (closes the loop) | ||
| **Conflict Resolution:** | ||
| - If multiple agents write to same section simultaneously, use section-level merge (append, don't overwrite). | ||
| - If same item ID used (`I1`, `C1`, `T1`), prefer most recent write (timestamp-based). | ||
| --- | ||
| ### Bloat Prevention (Pareto Principle) | ||
| **Daily Rotation:** | ||
| - Each day = new journal file: `logs/YYYY/YYYY-MM-DD.md` | ||
| - Previous days archived automatically (no manual cleanup needed) | ||
| - Keeps individual files lean (~500-1,500 lines max) | ||
| **Structured Updates:** | ||
| - Follow PERSONA.md rule: "3-4 sentences max" for agent-written content | ||
| - Use structured formats (`I{n}`, `C{n}`, `T{n}`) instead of verbose logs | ||
| - Free-form sections (Notes, Lessons) can be longer, but avoid repetition | ||
| **Rejection Criteria:** | ||
| - Validator rejects verbose agent updates: "Rewrite as summary" | ||
| - Avoid: "Agent wrote 500 lines of debug logs to Notes section" | ||
| - Prefer: "**C1:** Fixed sync bug - origin-aware dedupe (3-4 sentence summary)" | ||
| **Result:** | ||
| - Journal stays human-readable | ||
| - Parse time remains fast (< 100ms for 1,500 lines) | ||
| - UI rendering stays performant | ||
| - Self-evolution works (journal tracks issues → system fixes → journal stays lean) | ||
| --- | ||
| ### Example Journal Entry | ||
| ```markdown | ||
| # Log — 2025-11-05 | ||
| ## Completed ✅ | ||
| - **C1:** Fixed bidirectional journal sync | ||
| - Problem: Web edits didn't sync to CLI | ||
| - Solution: Added auto-pull when web is newer + local unchanged | ||
| - Impact: Users can edit on web (mobile) and changes sync automatically | ||
| ## In Progress 🔄 | ||
| - **T1:** Add Journal Protocol to atris.md | ||
| **Claimed by:** Executor at 2025-11-05 18:30 | ||
| **Status:** Writing protocol section | ||
| ## Backlog | ||
| - **T2:** Update package.json version | ||
| - **T3:** Test protocol spec with fresh init | ||
| ## Notes | ||
| ### Launch — Bidirectional Sync — 2025-11-05 10:30 | ||
| **What shipped:** | ||
| Enhanced sync logic with auto-pull and conflict resolution. | ||
| ## Inbox | ||
| (Inbox zero achieved) | ||
| ``` | ||
| **This format enables:** | ||
| - CLI: `grep "I1"` finds inbox items | ||
| - Web: Parses `I{n}` → renders as cards | ||
| - Agent: Reads Inbox → writes Backlog → coordinates via sections | ||
| --- | ||
| ## Phase 5.2: atrisDev Protocol (Universal Workflow) | ||
| **The atrisDev Protocol** is a universal workflow that any coding agent can follow to produce high-quality output. When agents follow this protocol, they build features systematically with human approval gates and proper documentation, using small, low-risk changes that compound over time. | ||
| **This protocol works with ANY agent:** Claude Code, Cursor, Windsurf, GitHub Copilot, or any LLM-based coding assistant. | ||
| --- | ||
| ### How to Use atrisDev | ||
| **Step 1: Load Context** | ||
| Run `atris` in your terminal. It outputs a prompt containing: | ||
| - Active work in progress | ||
| - Inbox ideas waiting to be built | ||
| - Recent completions | ||
| - The atrisDev workflow steps | ||
| **Step 2: Copy the Prompt** | ||
| Copy the entire output and paste it to your coding agent along with your task description. | ||
| **Step 3: Agent Follows the Protocol** | ||
| The agent executes this workflow: | ||
| --- | ||
| ### atrisDev Workflow Steps | ||
| **0. (Optional) Explore the Idea** | ||
| If requirements are unclear, use `atris brainstorm` (or a structured conversation) to explore the problem and possible approaches *before* committing to any plan: | ||
| - Clarify the problem, constraints, and “what good looks like”. | ||
| - Decide whether this should become a feature folder (`atris/features/[name]/`) or a small, direct TODO. | ||
| - Capture the refined idea into `atris/features/[name]/idea.md` once it is clear enough. | ||
| **1. Show atris Visualization** | ||
| Before writing any code, the agent creates a visual diagram showing: | ||
| - Architecture/data flow | ||
| - Key components and their interactions | ||
| - Database schema (if applicable) | ||
| - User experience flow (if applicable) | ||
| **Example:** | ||
| ``` | ||
| ┌─────────────┐ | ||
| │ Browser │ | ||
| └──────┬──────┘ | ||
| │ POST /api/features | ||
| ▼ | ||
| ┌─────────────────┐ ┌──────────────┐ | ||
| │ API Handler │─────▶│ Database │ | ||
| │ - Validate │ │ - features │ | ||
| │ - Transform │◀─────│ - users │ | ||
| └─────────────────┘ └──────────────┘ | ||
| │ | ||
| ▼ | ||
| ┌─────────────────┐ | ||
| │ Response JSON │ | ||
| └─────────────────┘ | ||
| ``` | ||
| **2. Wait for Approval** | ||
| Agent **MUST NOT** proceed until the human confirms the plan is correct. | ||
| **3. Create idea.md** | ||
| Path: `atris/features/[feature-name]/idea.md` | ||
| Contents: | ||
| - **Problem Statement** — What are we solving? | ||
| - **Solution Design** — How will we solve it? | ||
| - **ASCII Diagrams** — Visual representation | ||
| - **Success Criteria** — How do we know it works? | ||
| **4. Create build.md** | ||
| Path: `atris/features/[feature-name]/build.md` | ||
| Contents: | ||
| - **Step-by-step Implementation Plan** — Ordered list of tasks | ||
| - **Files to Change** — Exact file paths and what changes | ||
| - **Testing Strategy** — How to verify each step | ||
| **5. Execute Step by Step** | ||
| - Build one step at a time | ||
| - After each step, check alignment with the plan | ||
| - If something doesn't match, stop and adjust | ||
| - Never batch multiple steps without validation | ||
| **6. Review & Validate** | ||
| - Run all tests | ||
| - Verify success criteria from idea.md | ||
| - Update `atris/features/README.md` with new feature entry | ||
| - Add completion to journal: `## Completed ✅` | ||
| --- | ||
| ### Why This Works | ||
| **Benefits of atrisDev Protocol:** | ||
| - **Approval gates prevent wasted work** — Human confirms plan before execution | ||
| - **Documentation is automatic** — idea.md and build.md created as byproducts | ||
| - **Visual thinking reduces miscommunication** — ASCII diagrams force clarity | ||
| - **Step-by-step execution prevents sprawl** — Each step validated before next | ||
| - **Works with any agent** — Protocol is agent-agnostic | ||
| - **Spreads naturally** — Once installed, `atris` becomes the entry point for all dev work | ||
| **Adoption path:** | ||
| 1. Dev installs `atris`: `npm install -g atris` | ||
| 2. Initializes project: `atris init` | ||
| 3. Runs `atris` to get the protocol prompt | ||
| 4. Copies prompt to their preferred agent | ||
| 5. Agent follows atrisDev workflow → high-quality output | ||
| 6. Dev shares results → others adopt atris | ||
| **The vision:** Every developer running `atris` gets a structured, high-quality workflow regardless of which coding agent they use. The protocol becomes the standard. | ||
| --- | ||
| ## Phase 5.3: Claude Code Integration | ||
| Auto-inject Atris context into Claude Code sessions via skills and commands. | ||
| ### Slash Command Setup | ||
| Create `.claude/commands/atris.md`: | ||
| ```markdown | ||
| --- | ||
| description: Activate Atris context - loads TODO.md, journal, and persona | ||
| allowed-tools: Read, Bash, Glob, Grep | ||
| --- | ||
| # Atris Activate | ||
| Load these files: | ||
| 1. @atris/PERSONA.md (communication style) | ||
| 2. @atris/TODO.md (current tasks) | ||
| 3. @atris/MAP.md (navigation) | ||
| Workflow: plan → do → review | ||
| Rules: 3-4 sentences max, ASCII visuals, check MAP.md first | ||
| ``` | ||
| ### Skill Setup | ||
| Create `.claude/skills/atris/SKILL.md`: | ||
| ```markdown | ||
| --- | ||
| name: atris | ||
| description: Atris workspace navigation. Use when user mentions atris, TODO, tasks, MAP.md, or asks "where is X?" | ||
| allowed-tools: Read, Bash, Glob, Grep, Write, Edit | ||
| --- | ||
| # Atris Skill | ||
| Detect: Project has `atris/` folder with MAP.md, TODO.md, PERSONA.md | ||
| Workflow: Navigator (plan) → Executor (build) → Validator (verify) | ||
| Key behaviors: | ||
| - Read PERSONA.md first (3-4 sentences, ASCII visuals) | ||
| - Check MAP.md for file:line refs | ||
| - Update TODO.md (claim tasks, delete when done) | ||
| ``` | ||
| ### Checklist | ||
| - [ ] Create `.claude/commands/` directory | ||
| - [ ] Create `.claude/skills/atris/` directory | ||
| - [ ] Add `atris.md` command file | ||
| - [ ] Add `SKILL.md` skill file | ||
| - [ ] Test with `/atris` in Claude Code | ||
| - [ ] Verify skill triggers on "atris" or "tasks" mentions | ||
| --- | ||
| ## Phase 6: Future Roadmap (Vision) | ||
| **See [`Atris_NOTES.md`](./ATRIS_NOTES.md) for full roadmap. Preview:** | ||
| - **Phase 5a: Sync** — Local + cloud markdown sync, enabling offline editing and asynchronous agent work | ||
| - **Phase 5b: Sessions** — Step-by-step markdown workflows with `!status`, `!result` tags for interactive collaboration | ||
| - **Phase 5c: Crew Orchestration** — Multi-agent coordination (codebase expert → executor → validator) from markdown config | ||
| --- | ||
| ## Why This Works | ||
| 1. **MAP = Single Source of Truth** — All agents reference one navigation guide; no contradictions | ||
| 2. **Exact File:Line Context** — No guessing; every answer is pinpoint accurate | ||
| 3. **Self-Validating** — @validator_AGENT keeps MAP and artifacts fresh automatically | ||
| 4. **Scalable to Any Codebase** — Works for monorepos, microservices, solo projects, legacy systems | ||
| 5. **Agent Handoff** — New agent joins, reads MAP, immediately productive (no ramp-up time) | ||
| 6. **Offline + Async Ready** — Markdown files work offline; sync on schedule (future Phase 5a) | ||
| --- | ||
| ## Implementation Checklist | ||
| - [ ] **Install:** `npm install -g atris` (instant) | ||
| - [ ] **Init:** `atris init` - creates atris/ with templates (instant) | ||
| - [ ] **Phase 1:** AI agent generates MAP.md from codebase (5 min) | ||
| - [ ] **Phase 3:** AI agent generates TODO.md from MAP (2 min) | ||
| - [ ] **Validate:** Test navigator/executor/validator workflows (1 min) | ||
| - [ ] **Ongoing:** Run `atris update` to get template updates | ||
| **Total time to full instrumentation: ~8 minutes** | ||
| --- | ||
| ## Quick Start | ||
| ```bash | ||
| # Install globally | ||
| npm install -g atris | ||
| # Initialize in your project | ||
| cd /path/to/your/project | ||
| atris init | ||
| # Hand atris/atris.md to your AI agent with this prompt: | ||
| # "Read atris/atris.md. Execute Phase 1-4 to scaffold this system." | ||
| # Agent generates MAP.md, team/, and TODO.md in atris/ | ||
| # Your system is now fully instrumented for AI collaboration | ||
| # Keep atris.md updated | ||
| atris update | ||
| ``` | ||
| --- | ||
| **Status:** Production ready. Run `atris init` in any project to get: | ||
| 1. Pre-built agent templates (navigator, executor, validator) | ||
| 2. AI generates MAP.md from your codebase in <5 minutes | ||
| 3. AI generates TODO.md with exact file:line context | ||
| 4. Full workflow: activate → plan → build → validate | ||
| *Install once. Init anywhere. AI agents have instant context. Codebase becomes fully instrumented for AI collaboration.* |
| --- | ||
| name: create-member | ||
| description: "Create and manage AI team members using the MEMBER.md format. Use when the user wants to define a new AI role, set up a team member, create an agent persona, or work with team/MEMBER.md files." | ||
| version: 1.0.0 | ||
| tags: | ||
| - team | ||
| - member | ||
| - agent | ||
| - persona | ||
| --- | ||
| # Member Creator | ||
| Create AI team members using the MEMBER.md format. A member is a directory that bundles persona, skills, tools, and context into a deployable AI worker. | ||
| ## What is MEMBER.md | ||
| MEMBER.md defines a complete AI team member. It composes existing standards (SKILL.md for capabilities, .mcp.json for tool servers) into a single portable unit. | ||
| Spec: https://github.com/atrislabs/member | ||
| ## Directory Structure | ||
| ``` | ||
| team/<name>/ | ||
| ├── MEMBER.md REQUIRED Persona + role + permissions | ||
| ├── skills/ OPTIONAL SKILL.md files (capabilities) | ||
| │ └── <skill>/ | ||
| │ └── SKILL.md | ||
| ├── tools/ OPTIONAL MCP servers, API docs, CLI docs | ||
| │ ├── .mcp.json | ||
| │ └── <tool>.md | ||
| └── context/ OPTIONAL Domain knowledge (markdown) | ||
| └── *.md | ||
| ``` | ||
| ## Creating a Member | ||
| When the user asks to create a team member, follow these steps: | ||
| ### Step 1: Ask what role | ||
| Ask the user: | ||
| - What role is this member? (e.g., SDR, support agent, code reviewer) | ||
| - What should they be able to do? | ||
| - What should they NOT be able to do? | ||
| ### Step 2: Create the directory | ||
| ``` | ||
| team/<name>/ | ||
| ├── MEMBER.md | ||
| ├── skills/ | ||
| ├── tools/ | ||
| └── context/ | ||
| ``` | ||
| Use kebab-case for the name. Create all four directories even if empty. | ||
| ### Step 3: Write MEMBER.md | ||
| Use this structure: | ||
| ```yaml | ||
| --- | ||
| name: <kebab-case-name> | ||
| role: <Human Readable Title> | ||
| description: <one line — what this member does> | ||
| version: 1.0.0 | ||
| skills: [] | ||
| permissions: | ||
| can-read: true | ||
| --- | ||
| ``` | ||
| Below the frontmatter, write three sections: | ||
| **Persona** — How the member communicates. Tone, style, decision-making approach. Be specific — "direct and research-driven" is better than "professional and helpful." | ||
| **Workflow** — Numbered steps the member follows. This is the core operating procedure. Each step should be a concrete action. | ||
| **Rules** — Hard constraints. What the member must always or never do. Keep it to 3-5 rules. | ||
| ### Step 4: Add permissions | ||
| Common permission patterns: | ||
| ```yaml | ||
| # Read-only member (planner, researcher) | ||
| permissions: | ||
| can-read: true | ||
| can-execute: false | ||
| # Builder with guardrails | ||
| permissions: | ||
| can-read: true | ||
| can-execute: true | ||
| can-delete: false | ||
| approval-required: [delete, deploy] | ||
| # Full access (reviewer, admin) | ||
| permissions: | ||
| can-read: true | ||
| can-execute: true | ||
| can-approve: true | ||
| can-ship: true | ||
| ``` | ||
| Permissions are declarations, not enforcement. They tell the agent what its boundaries are. The agent respects them because they're in its instructions. | ||
| ### Step 5: Add skills (optional) | ||
| If the member needs specific capabilities, create SKILL.md files: | ||
| ``` | ||
| team/<name>/skills/<skill-name>/SKILL.md | ||
| ``` | ||
| Each skill follows the standard SKILL.md format: | ||
| ```yaml | ||
| --- | ||
| name: <skill-name> | ||
| description: <what this skill does> | ||
| --- | ||
| # <Skill Name> | ||
| <Instructions for how to perform this capability> | ||
| ``` | ||
| Update the member's frontmatter to list the skill: | ||
| ```yaml | ||
| skills: | ||
| - <skill-name> | ||
| ``` | ||
| ### Step 6: Add context (optional) | ||
| Drop markdown files into `context/` with domain knowledge the member needs: | ||
| - Playbooks, SOPs, guidelines | ||
| - Customer profiles, ICPs | ||
| - Reference docs, templates | ||
| No special format. Just markdown files the member references. | ||
| ## Flat File Format | ||
| For simple members that just need a persona (no skills, tools, or context), use a flat file: | ||
| ``` | ||
| team/<name>.md | ||
| ``` | ||
| Same frontmatter, same format. Just no directory structure around it. | ||
| ## Detection | ||
| Add to your project's CLAUDE.md (or AGENTS.md for Codex): | ||
| ```markdown | ||
| ## Team | ||
| This project uses MEMBER.md team members in `team/`. | ||
| When activated as a specific member, read `team/<name>/MEMBER.md`. | ||
| ``` | ||
| ## Multi-Agent Usage | ||
| Activate different members for different tasks: | ||
| ``` | ||
| "Act as the navigator. Read team/navigator/MEMBER.md and plan this feature." | ||
| "Act as the validator. Read team/validator/MEMBER.md and review these changes." | ||
| ``` | ||
| Each member gets its own persona, skills, permissions, and context. | ||
| ## Examples | ||
| ### Dev team member (code reviewer) | ||
| ```yaml | ||
| --- | ||
| name: reviewer | ||
| role: Code Reviewer | ||
| description: Reviews PRs for correctness, security, and style | ||
| version: 1.0.0 | ||
| skills: [] | ||
| permissions: | ||
| can-read: true | ||
| can-approve: true | ||
| can-execute: false | ||
| --- | ||
| ## Persona | ||
| Thorough but not pedantic. You catch real bugs, not style nits. | ||
| If something works and is readable, approve it. | ||
| ## Workflow | ||
| 1. Read the diff | ||
| 2. Check for bugs, security issues, breaking changes | ||
| 3. Approve or request specific changes (no vague feedback) | ||
| ## Rules | ||
| 1. Never block on style alone | ||
| 2. Every comment must be actionable | ||
| 3. If unsure, approve with a note | ||
| ``` | ||
| ### Business role (SDR) | ||
| ```yaml | ||
| --- | ||
| name: sdr | ||
| role: Sales Development Rep | ||
| description: Outbound prospecting and lead qualification | ||
| version: 1.0.0 | ||
| skills: | ||
| - email-outreach | ||
| - lead-research | ||
| permissions: | ||
| can-draft: true | ||
| can-send: false | ||
| approval-required: [send, delete] | ||
| tools: | ||
| - hubspot | ||
| - apollo | ||
| --- | ||
| ## Persona | ||
| Research-driven. Every email references something specific about | ||
| the prospect. If you can't find a hook, don't send. | ||
| ## Workflow | ||
| 1. Research the lead | ||
| 2. Qualify against ICP (context/icp.md) | ||
| 3. Draft personalized sequence | ||
| 4. Flag for human approval | ||
| ## Rules | ||
| 1. Never send without approval | ||
| 2. Every email must reference something specific | ||
| 3. Log everything to CRM | ||
| ``` |
| --- | ||
| name: x-search | ||
| description: "X/Twitter search via xAI Grok API. Use when user wants to search tweets, monitor topics, find viral posts, or run social listening. Costs 5 credits per search. Triggers on x search, tweet search, twitter search, social listening, revenue intel, viral tweets." | ||
| version: 1.0.0 | ||
| tags: | ||
| - x-search | ||
| - social | ||
| - research | ||
| --- | ||
| # x-search | ||
| Search X/Twitter via xAI's Grok API. 5 credits per search action. Returns tweets with full text, author, engagement metrics, and citations. | ||
| ## Quick Search | ||
| ```python | ||
| cd backend | ||
| source ../venv/bin/activate | ||
| ``` | ||
| ```python | ||
| import asyncio | ||
| from dotenv import load_dotenv | ||
| load_dotenv('.env') | ||
| from clients.xai import XAIClient, bill_xai_action | ||
| # 1. Bill the user (5 credits) | ||
| bill = await bill_xai_action(USER_ID, "x_search") | ||
| if not bill["ok"]: | ||
| print(f"Insufficient credits: {bill['error']}") | ||
| # 2. Search | ||
| client = XAIClient() | ||
| result = await client.search_x('"CRM is dead" OR "Salesforce is dead"', limit=10) | ||
| print(result["content"]) | ||
| print(f"Usage: {result['usage']}") | ||
| ``` | ||
| ## Date-Constrained Search (last N days) | ||
| ```python | ||
| from xai_sdk.chat import user as xai_user | ||
| client = XAIClient() | ||
| tools = client._get_tools() | ||
| chat = client._get_client().chat.create( | ||
| model="grok-4-1-fast", | ||
| tools=[tools.x_search()], | ||
| ) | ||
| chat.append(xai_user(f"""Search X/Twitter for: "your query here" | ||
| IMPORTANT: Only return tweets posted within the last 7 days. | ||
| Return the 10 most relevant posts with: | ||
| - Full tweet text (quoted exactly) | ||
| - Author handle | ||
| - Exact date/time | ||
| - Engagement (likes, retweets, views) | ||
| Prioritize posts with high engagement (likes > 5, views > 1000).""")) | ||
| content = "" | ||
| for response, chunk in chat.stream(): | ||
| if chunk.content: | ||
| content += chunk.content | ||
| print(content) | ||
| ``` | ||
| ## Revenue Intel Digest (multi-cluster) | ||
| ```python | ||
| from atris.team.gtm.skills.revenue_intel import run_digest, format_for_slack | ||
| # Runs 5 keyword clusters, drafts replies for top 5 items | ||
| # Cost: 5 credits per cluster = 25 credits total | ||
| result = await run_digest( | ||
| days_back=1, | ||
| user_id=USER_ID, | ||
| draft_count=5, | ||
| ) | ||
| print(result["digest"]) # Ranked results by cluster | ||
| print(result["drafts"]) # Reply options A/B per item | ||
| print(result["credits_used"]) | ||
| # Format for Slack delivery | ||
| slack_msg = await format_for_slack(result) | ||
| ``` | ||
| ## Custom Keyword Clusters | ||
| ```python | ||
| my_clusters = { | ||
| "competitors": '"Competitor Name" (review OR complaint OR switching OR alternative)', | ||
| "industry_pain": '"your industry" (frustrated OR broken OR replacing OR ripping out)', | ||
| "thought_leaders": '(founder OR CEO OR CTO) ("your topic" OR "related topic") min_faves:10', | ||
| } | ||
| result = await run_digest(clusters=my_clusters, user_id=USER_ID, days_back=7) | ||
| ``` | ||
| ## Billing | ||
| 1. Every xAI action costs **5 credits** (flat) | ||
| 2. 1 credit = $0.01, so 1 search = $0.05 | ||
| 3. `bill_xai_action(user_id, action_name)` checks balance and deducts before the call | ||
| 4. Returns `{"ok": False, "error": "Insufficient credits"}` if balance < 5 | ||
| 5. Transaction logged as `txn_type="xai_action"` in `credit_transactions` | ||
| | Plan | Monthly Credits | Searches/Month | | ||
| |------|----------------|----------------| | ||
| | Free | 50 | 10 | | ||
| | Pro ($20/mo) | 1,000 | 200 | | ||
| | Max ($200/mo) | unlimited | unlimited | | ||
| | Credit pack ($10) | 1,000 | 200 | | ||
| ## Cost Breakdown | ||
| | Component | Cost to us | What it does | | ||
| |-----------|-----------|--------------| | ||
| | xAI x_search tool | $0.005/call | Searches X, returns batch of tweets | | ||
| | grok-4-1-fast tokens | ~$0.003/call | Processes and formats results | | ||
| | Total per search | ~$0.008 | Raw cost | | ||
| | We charge | $0.05 (5 credits) | 84% margin | | ||
| ## Key Files | ||
| | File | What | | ||
| |------|------| | ||
| | `backend/clients/xai.py` | XAIClient + bill_xai_action() | | ||
| | `atris/team/gtm/skills/revenue_intel.py` | Multi-cluster digest pipeline | | ||
| | `backend/tools/core/reply_guy_tool.py` | Reply generation tool (bills 5 credits) | | ||
| | `backend/tools/integrations/research_tweet_tool.py` | Research + tweet tool (bills 5 credits) | | ||
| ## Rules | ||
| 1. Always bill before searching — never search without `bill_xai_action()` | ||
| 2. Date filtering is prompt-based, not API-level — include explicit date cutoff in prompt | ||
| 3. Use `min_faves:N` in queries to filter low-engagement noise | ||
| 4. Never auto-post tweets — always require user approval | ||
| 5. Internal usage (no user_id) skips billing — platform absorbs cost |
| --- | ||
| name: researcher | ||
| role: Deep Researcher | ||
| description: Find ground truth on any topic — competitors, standards, technologies, markets | ||
| version: 1.0.0 | ||
| skills: [] | ||
| permissions: | ||
| can-read: true | ||
| can-execute: false | ||
| can-plan: false | ||
| can-approve: false | ||
| --- | ||
| # Researcher — Deep Researcher | ||
| > **Source:** Questions from any team member, inbox items tagged [research] | ||
| > **Style:** Read `atris/PERSONA.md` for communication style. | ||
| --- | ||
| ## Persona | ||
| Obsessively thorough but fast. You don't summarize — you find primary sources, verify claims, and surface what others miss. You have a bias toward "what's actually true" over "what sounds right." If you can't verify something, you say so instead of guessing. | ||
| Direct. No filler. Every sentence either presents evidence or connects evidence to a conclusion. | ||
| --- | ||
| ## Workflow | ||
| 1. **Clarify the question** — Restate what you're researching in one sentence. If the question is vague, narrow it before you start. | ||
| 2. **Find primary sources** — Web search, read repos, read docs. Go to the source. Blog posts and summaries are leads, not evidence. | ||
| 3. **Verify claims** — If something sounds important, check it from a second source. Flag anything you couldn't verify. | ||
| 4. **Synthesize** — Organize findings into a structured brief: what's true, what's uncertain, what's missing. | ||
| 5. **Deliver the brief** — Hand off to whoever asked. Include sources for every claim. | ||
| --- | ||
| ## Output Format | ||
| ``` | ||
| ## Research Brief: [Topic] | ||
| ### Question | ||
| [One sentence — what we're trying to answer] | ||
| ### Findings | ||
| - [Claim] — [Source URL or file:line] | ||
| - [Claim] — [Source URL or file:line] | ||
| - [Claim] — [Source URL or file:line] | ||
| ### Unverified | ||
| - [Claim that needs a second source] | ||
| ### Gaps | ||
| - [What we still don't know] | ||
| ### So What | ||
| [2-3 sentences — what this means for us, what to do with it] | ||
| ``` | ||
| --- | ||
| ## Rules | ||
| 1. Every claim needs a source. No source = flag it as unverified. | ||
| 2. Primary sources over summaries. Read the repo, not the blog post about the repo. | ||
| 3. Say "I don't know" when you don't know. Never fill gaps with plausible-sounding guesses. | ||
| 4. Keep it short. A research brief is a page, not a paper. | ||
| 5. DO NOT execute, plan, or build. You find truth. Others act on it. |
| --- | ||
| name: atris | ||
| description: Codebase intelligence — generates structured navigation maps with file:line references so agents stop re-scanning the same files every session. Use when exploring code, answering "where is X?", or onboarding to a new codebase. | ||
| description: "Codebase intelligence — generates structured navigation maps with file:line references so agents stop re-scanning the same files every session. Use when exploring code, answering 'where is X?', or onboarding to a new codebase." | ||
| version: 1.1.0 | ||
@@ -5,0 +5,0 @@ requires: |
| --- | ||
| name: drive | ||
| description: Google Drive integration via AtrisOS API. Browse, search, read, upload files and work with Google Sheets. Use when user asks about Drive, files, docs, sheets, or spreadsheets. | ||
| version: 1.1.0 | ||
| version: 1.2.0 | ||
| tags: | ||
@@ -202,2 +202,25 @@ - drive | ||
| ### Update Existing File | ||
| ```bash | ||
| curl -s -X PUT "https://api.atris.ai/api/integrations/google-drive/files/{file_id}" \ | ||
| -H "Authorization: Bearer $TOKEN" \ | ||
| -H "Content-Type: application/json" \ | ||
| -d '{ | ||
| "content": "Updated file content here", | ||
| "mime_type": "text/plain" | ||
| }' | ||
| ``` | ||
| **Update content and rename:** | ||
| ```bash | ||
| curl -s -X PUT "https://api.atris.ai/api/integrations/google-drive/files/{file_id}" \ | ||
| -H "Authorization: Bearer $TOKEN" \ | ||
| -H "Content-Type: application/json" \ | ||
| -d '{ | ||
| "content": "New content", | ||
| "mime_type": "text/plain", | ||
| "name": "renamed-file.txt" | ||
| }' | ||
| ``` | ||
| --- | ||
@@ -303,2 +326,10 @@ | ||
| ### "Edit a file on Drive" | ||
| 1. Run bootstrap | ||
| 2. Find the file: `GET /google-drive/search?q=FILENAME` | ||
| 3. Read current content: `GET /google-drive/files/{id}/export?mime_type=text/plain` | ||
| 4. Make edits | ||
| 5. **Show user the changes for approval** | ||
| 6. Update: `PUT /google-drive/files/{id}` with `{content, mime_type}` | ||
| --- | ||
@@ -361,6 +392,11 @@ | ||
| # Upload a file | ||
| # Upload a new file | ||
| curl -s -X POST "https://api.atris.ai/api/integrations/google-drive/files" \ | ||
| -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ | ||
| -d '{"name":"notes.txt","content":"Hello world","mime_type":"text/plain"}' | ||
| # Update an existing file | ||
| curl -s -X PUT "https://api.atris.ai/api/integrations/google-drive/files/{file_id}" \ | ||
| -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ | ||
| -d '{"content":"Updated content","mime_type":"text/plain"}' | ||
| ``` |
@@ -253,2 +253,13 @@ --- | ||
| ### Mark as Read / Unread | ||
| ```bash | ||
| # Mark as read | ||
| curl -s -X POST "https://api.atris.ai/api/integrations/gmail/messages/{message_id}/read" \ | ||
| -H "Authorization: Bearer $TOKEN" | ||
| # Mark as unread | ||
| curl -s -X POST "https://api.atris.ai/api/integrations/gmail/messages/{message_id}/unread" \ | ||
| -H "Authorization: Bearer $TOKEN" | ||
| ``` | ||
| ### Archive Email | ||
@@ -267,2 +278,15 @@ ```bash | ||
| ### Trash Email | ||
| ```bash | ||
| # Single message | ||
| curl -s -X POST "https://api.atris.ai/api/integrations/gmail/messages/{message_id}/trash" \ | ||
| -H "Authorization: Bearer $TOKEN" | ||
| # Batch trash | ||
| curl -s -X POST "https://api.atris.ai/api/integrations/gmail/messages/batch-trash" \ | ||
| -H "Authorization: Bearer $TOKEN" \ | ||
| -H "Content-Type: application/json" \ | ||
| -d '{"message_ids": ["id1", "id2", "id3"]}' | ||
| ``` | ||
| ### Check Status | ||
@@ -415,2 +439,8 @@ ```bash | ||
| # Mark as read | ||
| curl -s -X POST "https://api.atris.ai/api/integrations/gmail/messages/{message_id}/read" -H "Authorization: Bearer $TOKEN" | ||
| # Trash an email | ||
| curl -s -X POST "https://api.atris.ai/api/integrations/gmail/messages/{message_id}/trash" -H "Authorization: Bearer $TOKEN" | ||
| # Send a draft | ||
@@ -417,0 +447,0 @@ curl -s -X POST "https://api.atris.ai/api/integrations/gmail/drafts/{draft_id}/send" \ |
| --- | ||
| name: slack | ||
| description: Slack integration via AtrisOS API. Read messages, send as yourself, search conversations, manage DMs. Use when user asks about Slack, messages, channels, or team communication. | ||
| version: 1.0.0 | ||
| version: 1.1.0 | ||
| tags: | ||
@@ -190,2 +190,10 @@ - slack | ||
| ### Search Users | ||
| ```bash | ||
| curl -s "https://api.atris.ai/api/integrations/slack/users/search?q=justin" \ | ||
| -H "Authorization: Bearer $TOKEN" | ||
| ``` | ||
| Searches by name, display name, or email. Much faster than pulling the full user list. | ||
| ### Send as Bot | ||
@@ -227,5 +235,5 @@ ```bash | ||
| 1. Run bootstrap | ||
| 2. Find the user: `GET /slack/users` (search by name/email) | ||
| 2. Find the user: `GET /slack/users/search?q=NAME` | ||
| 3. **Show user the draft for approval** | ||
| 4. Send DM: `POST /slack/me/dm` with `{user_id, text}` | ||
| 4. Send DM: `POST /slack/me/dm` with `{slack_user_id, text}` | ||
| 5. Confirm: "Message sent!" | ||
@@ -248,3 +256,3 @@ | ||
| 1. Run bootstrap | ||
| 2. List users: `GET /slack/users` (find user ID) | ||
| 2. Find user: `GET /slack/users/search?q=NAME` (get user ID) | ||
| 3. List DMs: `GET /slack/me/dms` (find DM channel with that user) | ||
@@ -323,2 +331,5 @@ 4. Read messages: `GET /slack/me/messages/{channel_id}` | ||
| curl -s "https://api.atris.ai/api/integrations/slack/users" -H "Authorization: Bearer $TOKEN" | ||
| # Search users by name | ||
| curl -s "https://api.atris.ai/api/integrations/slack/users/search?q=justin" -H "Authorization: Bearer $TOKEN" | ||
| ``` |
@@ -125,3 +125,3 @@ /** | ||
| try { | ||
| const cmd = `claude -p "$(cat ${tmpFile})" --allowedTools "Bash,Read,Write,Edit,Glob,Grep"`; | ||
| const cmd = `claude -p "$(cat '${tmpFile.replace(/'/g, "'\\''")}')" --allowedTools "Bash,Read,Write,Edit,Glob,Grep"`; | ||
| const output = execSync(cmd, { | ||
@@ -138,3 +138,3 @@ cwd: process.cwd(), | ||
| const result = verbose ? '' : output; | ||
| const result = output || ''; | ||
@@ -313,2 +313,6 @@ if (phase === 'plan') { | ||
| // Clean up temp files on success | ||
| try { fs.unlinkSync(path.join(process.cwd(), 'prd.json')); } catch {} | ||
| try { fs.unlinkSync(path.join(process.cwd(), 'progress.txt')); } catch {} | ||
| return { success: true, iterations: iteration }; | ||
@@ -366,3 +370,7 @@ } | ||
| const backlogLines = backlogMatch[1].split('\n').filter(line => line.trim().startsWith('- [ ]')); | ||
| // Support both formats: "- [ ] Task" (checkbox) and "- **T1:** Task" (Atris standard) | ||
| const backlogLines = backlogMatch[1].split('\n').filter(line => { | ||
| const trimmed = line.trim(); | ||
| return trimmed.startsWith('- [ ]') || trimmed.match(/^- \*\*T\d+:\*\*\s/); | ||
| }); | ||
@@ -375,4 +383,5 @@ if (backlogLines.length === 0) { | ||
| // Pick first item | ||
| const firstItem = backlogLines[0]; | ||
| const itemMatch = firstItem.match(/- \[ \] (.+)/); | ||
| const firstItem = backlogLines[0].trim(); | ||
| // Try checkbox format first, then Atris standard format | ||
| const itemMatch = firstItem.match(/- \[ \] (.+)/) || firstItem.match(/- \*\*T\d+:\*\*\s*(.+)/); | ||
@@ -379,0 +388,0 @@ if (!itemMatch) { |
@@ -243,3 +243,3 @@ const fs = require('fs'); | ||
| for (const r of replacements) { | ||
| mapContent = mapContent.replace(r.old, r.new); | ||
| mapContent = mapContent.split(r.old).join(r.new); | ||
| } | ||
@@ -246,0 +246,0 @@ fs.writeFileSync(mapFile, mapContent); |
+11
-5
@@ -160,5 +160,5 @@ const fs = require('fs'); | ||
| function injectProjectPatterns(agentTeamDir, profile) { | ||
| const executorFile = path.join(agentTeamDir, 'executor.md'); | ||
| const navigatorFile = path.join(agentTeamDir, 'navigator.md'); | ||
| const validatorFile = path.join(agentTeamDir, 'validator.md'); | ||
| const executorFile = path.join(agentTeamDir, 'executor', 'MEMBER.md'); | ||
| const navigatorFile = path.join(agentTeamDir, 'navigator', 'MEMBER.md'); | ||
| const validatorFile = path.join(agentTeamDir, 'validator', 'MEMBER.md'); | ||
@@ -802,4 +802,10 @@ // Inject into executor.md | ||
| const startIdx = content.indexOf(startMarker); | ||
| const endIdx = content.indexOf(endMarker) + endMarker.length; | ||
| content = atrisBlock + content.slice(0, startIdx) + content.slice(endIdx).replace(/^\n+/, ''); | ||
| const endRaw = content.indexOf(endMarker); | ||
| if (endRaw === -1) { | ||
| // End marker missing — replace from start marker to end with fresh block | ||
| content = atrisBlock + content.slice(0, startIdx); | ||
| } else { | ||
| const endIdx = endRaw + endMarker.length; | ||
| content = atrisBlock + content.slice(0, startIdx) + content.slice(endIdx).replace(/^\n+/, ''); | ||
| } | ||
| fs.writeFileSync(rootClaudeMd, content); | ||
@@ -806,0 +812,0 @@ console.log('✓ Updated Atris block in CLAUDE.md'); |
@@ -192,4 +192,6 @@ const fs = require('fs'); | ||
| // 11. under 5000 words | ||
| const wordCount = skill.content.split(/\s+/).length; | ||
| // 11. under 5000 words (body only, excluding frontmatter) | ||
| const bodyStart = skill.content.indexOf('---', skill.content.indexOf('---') + 3); | ||
| const bodyContent = bodyStart >= 0 ? skill.content.slice(bodyStart + 3) : skill.content; | ||
| const wordCount = bodyContent.split(/\s+/).filter(Boolean).length; | ||
| checks.push({ | ||
@@ -479,3 +481,3 @@ id: 'word-count', | ||
| name: ${name} | ||
| description: ${description || `Custom skill for ${name}. Use when user asks about ${name}-related tasks.`} | ||
| description: "${(description || `Custom skill for ${name}. Use when user asks about ${name}-related tasks.`).replace(/"/g, '\\"')}" | ||
| version: 1.0.0 | ||
@@ -591,3 +593,3 @@ tags: | ||
| if (!nameArg) { | ||
| console.error('Usage: atris skill create <name> [--integration] [--description="..."] [--system]'); | ||
| console.error('Usage: atris skill create <name> [--integration] [--description="..."] [--local]'); | ||
| console.error(''); | ||
@@ -598,3 +600,3 @@ console.error('Examples:'); | ||
| console.error(' atris skill create pallet/bol-processor --integration'); | ||
| console.error(' atris skill create my-skill --system'); | ||
| console.error(' atris skill create my-skill --local # project only, skip system dirs'); | ||
| process.exit(1); | ||
@@ -601,0 +603,0 @@ } |
+20
-10
@@ -68,2 +68,3 @@ const fs = require('fs'); | ||
| { source: 'atris/team/brainstormer/MEMBER.md', target: 'team/brainstormer/MEMBER.md' }, | ||
| { source: 'atris/team/researcher/MEMBER.md', target: 'team/researcher/MEMBER.md' }, | ||
| { source: 'atris/policies/ANTISLOP.md', target: 'policies/ANTISLOP.md' } | ||
@@ -171,4 +172,5 @@ ]; | ||
| fs.mkdirSync(symlinkPath, { recursive: true }); | ||
| if (fs.existsSync(destSkillFile)) { | ||
| fs.copyFileSync(destSkillFile, path.join(symlinkPath, 'SKILL.md')); | ||
| const skillFile = path.join(destSkillDir, 'SKILL.md'); | ||
| if (fs.existsSync(skillFile)) { | ||
| fs.copyFileSync(skillFile, path.join(symlinkPath, 'SKILL.md')); | ||
| } | ||
@@ -267,12 +269,20 @@ console.log(`✓ Copied .claude/skills/${skill} (symlink failed)`); | ||
| const startIdx = content.indexOf(startMarker); | ||
| const endIdx = content.indexOf(endMarker) + endMarker.length; | ||
| const existingBlock = content.slice(startIdx, endIdx); | ||
| const newBlockTrimmed = atrisBlock.trim().slice(0, -1); // Remove trailing newline for comparison | ||
| if (!existingBlock.includes('Atris boot sequence')) { | ||
| // Replace existing Atris block with new version | ||
| content = atrisBlock + content.slice(0, startIdx) + content.slice(endIdx).replace(/^\n+/, ''); | ||
| const endRaw = content.indexOf(endMarker); | ||
| if (endRaw === -1) { | ||
| // End marker missing — replace from start marker to end of file with fresh block | ||
| content = atrisBlock + content.slice(0, startIdx); | ||
| fs.writeFileSync(rootClaudeMd, content); | ||
| console.log('✓ Updated Atris block in CLAUDE.md'); | ||
| console.log('✓ Repaired Atris block in CLAUDE.md (missing end marker)'); | ||
| updated++; | ||
| } else { | ||
| const endIdx = endRaw + endMarker.length; | ||
| const existingBlock = content.slice(startIdx, endIdx); | ||
| if (!existingBlock.includes('Atris boot sequence')) { | ||
| // Replace existing Atris block with new version | ||
| content = atrisBlock + content.slice(0, startIdx) + content.slice(endIdx).replace(/^\n+/, ''); | ||
| fs.writeFileSync(rootClaudeMd, content); | ||
| console.log('✓ Updated Atris block in CLAUDE.md'); | ||
| updated++; | ||
| } | ||
| } | ||
@@ -279,0 +289,0 @@ } else { |
+2
-40
@@ -384,42 +384,4 @@ const fs = require('fs'); | ||
| // Extract tasks from TODO.md (no tag filtering - all tasks available) | ||
| const taskTag = ''; | ||
| let filteredTasks = ''; | ||
| if (taskTag && tasksContent) { | ||
| const taskLines = tasksContent.split('\n'); | ||
| let inTasksSection = false; | ||
| let currentTask = []; | ||
| for (const line of taskLines) { | ||
| if (line.includes('<tasks>')) { | ||
| inTasksSection = true; | ||
| continue; | ||
| } | ||
| if (line.includes('</tasks>')) { | ||
| inTasksSection = false; | ||
| if (currentTask.length > 0) { | ||
| filteredTasks += currentTask.join('\n') + '\n\n'; | ||
| } | ||
| currentTask = []; | ||
| continue; | ||
| } | ||
| if (inTasksSection && line.trim()) { | ||
| if (line.includes(taskTag)) { | ||
| currentTask = [line]; | ||
| } else if (currentTask.length > 0) { | ||
| currentTask.push(line); | ||
| } | ||
| } | ||
| } | ||
| if (currentTask.length > 0) { | ||
| filteredTasks += currentTask.join('\n') + '\n'; | ||
| } | ||
| } else { | ||
| filteredTasks = tasksContent; | ||
| } | ||
| // Load TODO.md content (using existing task file variable) | ||
| let taskContexts = ''; | ||
| if (taskFilePath && fs.existsSync(taskFilePath)) { | ||
| taskContexts = fs.readFileSync(taskFilePath, 'utf8'); | ||
| } | ||
| // All tasks available (no tag filtering) | ||
| const filteredTasks = tasksContent; | ||
@@ -426,0 +388,0 @@ const executorPath = path.relative(process.cwd(), executorFile); |
+1
-1
@@ -74,3 +74,3 @@ const fs = require('fs'); | ||
| const initialContent = `# Log — ${dateFormatted}\n\n## Completed ✅\n\n---\n\n## In Progress 🔄\n\n${inProgressBody}---\n\n## Backlog\n\n${backlogBody}---\n\n## Notes\n\n---\n\n## Inbox\n\n${inboxBody}\n`; | ||
| const initialContent = `# Log — ${dateFormatted}\n\n## Handoff\n\n---\n\n## Completed ✅\n\n---\n\n## In Progress 🔄\n\n${inProgressBody}---\n\n## Backlog\n\n${backlogBody}---\n\n## Notes\n\n---\n\n## Inbox\n\n${inboxBody}\n`; | ||
| fs.writeFileSync(logFile, initialContent); | ||
@@ -77,0 +77,0 @@ } |
+14
-11
@@ -55,2 +55,9 @@ const crypto = require('crypto'); | ||
| // Check if the full remote document matches the known state. | ||
| // knownRemoteHash is a hash of the entire document at last sync. | ||
| // If it matches, remote hasn't changed — prefer all local edits. | ||
| const remoteReconstructed = reconstructJournal(remoteSections); | ||
| const currentRemoteHash = computeContentHash(remoteReconstructed); | ||
| const remoteUnchanged = knownRemoteHash && currentRemoteHash === knownRemoteHash; | ||
| // Get all unique section names | ||
@@ -72,13 +79,9 @@ const allSections = new Set([...Object.keys(localSections), ...Object.keys(remoteSections)]); | ||
| merged[section] = remoteContent; | ||
| } else if (remoteUnchanged) { | ||
| // Remote hasn't changed since last sync, prefer local | ||
| merged[section] = localContent; | ||
| } else { | ||
| // Both exist but differ - check if remote matches known state | ||
| const remoteHash = computeContentHash(remoteContent); | ||
| if (knownRemoteHash && remoteHash === knownRemoteHash) { | ||
| // Remote hasn't changed since last sync, prefer local | ||
| merged[section] = localContent; | ||
| } else { | ||
| // Real conflict - mark for user review | ||
| conflicts.push(section); | ||
| merged[section] = localContent; // Default to local | ||
| } | ||
| // Real conflict - mark for user review | ||
| conflicts.push(section); | ||
| merged[section] = localContent; // Default to local | ||
| } | ||
@@ -114,3 +117,3 @@ } | ||
| return parts.join('\n'); | ||
| return parts.join(''); | ||
| } | ||
@@ -117,0 +120,0 @@ |
@@ -191,3 +191,3 @@ const fs = require('fs'); | ||
| const content = fs.readFileSync(taskFilePath, 'utf8'); | ||
| if (content.includes('Risk Level: High') || content.includes('blocked')) { | ||
| if (content.includes('Risk Level: High') || /\bblocked\b/i.test(content)) { | ||
| return { state: 'blocked', reason: 'Tasks marked as blocked or high risk' }; | ||
@@ -278,3 +278,4 @@ } | ||
| getBacklogTasks, | ||
| getInProgressTasks | ||
| getInProgressTasks, | ||
| getCompletedTasks | ||
| }; |
+2
-1
| { | ||
| "name": "atris", | ||
| "version": "2.3.5", | ||
| "version": "2.3.7", | ||
| "description": "atrisDev (atris dev) - CLI for AI coding agents. Works with Claude Code, Cursor, Windsurf. Make any codebase AI-navigable.", | ||
@@ -20,2 +20,3 @@ "main": "bin/atris.js", | ||
| "PERSONA.md", | ||
| "atris/atrisDev.md", | ||
| "atris/CLAUDE.md", | ||
@@ -22,0 +23,0 @@ "atris/GEMINI.md", |
+24
-0
@@ -224,2 +224,21 @@ const https = require('https'); | ||
| res.on('end', () => { | ||
| // Flush any remaining buffered data | ||
| if (buffer.trim()) { | ||
| const line = buffer.trim(); | ||
| if (line.startsWith('data: ')) { | ||
| const data = line.slice(6).trim(); | ||
| if (data && data !== '[DONE]') { | ||
| try { | ||
| const msg = JSON.parse(data); | ||
| if (msg.chunk) { | ||
| process.stdout.write(msg.chunk); | ||
| } else if (msg.type === 'result' && msg.result) { | ||
| process.stdout.write(msg.result); | ||
| } | ||
| } catch (e) { | ||
| // Ignore parse errors on final flush | ||
| } | ||
| } | ||
| } | ||
| } | ||
| resolve(); | ||
@@ -233,2 +252,7 @@ }); | ||
| // Timeout after 2 minutes of no response | ||
| req.setTimeout(120000, () => { | ||
| req.destroy(new Error('SSE stream timed out after 120s')); | ||
| }); | ||
| req.on('error', (err) => { | ||
@@ -235,0 +259,0 @@ reject(err); |
+7
-4
@@ -9,10 +9,12 @@ const os = require('os'); | ||
| const platform = os.platform(); | ||
| // Sanitize URL to prevent shell injection — only allow valid URL characters | ||
| const sanitizedUrl = url.replace(/[^a-zA-Z0-9\-._~:/?#\[\]@!$&'()*+,;=%]/g, ''); | ||
| let command; | ||
| if (platform === 'darwin') { | ||
| command = `open "${url}"`; | ||
| command = `open "${sanitizedUrl}"`; | ||
| } else if (platform === 'win32') { | ||
| command = `start "${url}"`; | ||
| command = `start "" "${sanitizedUrl}"`; | ||
| } else { | ||
| command = `xdg-open "${url}"`; | ||
| command = `xdg-open "${sanitizedUrl}"`; | ||
| } | ||
@@ -137,3 +139,4 @@ | ||
| // "keshav@atrislabs.com" → "keshav" | ||
| return email.split('@')[0].toLowerCase().replace(/[^a-z0-9_-]/g, '-'); | ||
| const name = email.split('@')[0].toLowerCase().replace(/[^a-z0-9_-]/g, '-'); | ||
| return name || null; // Guard against emails like "@domain.com" | ||
| } | ||
@@ -140,0 +143,0 @@ |
Sorry, the diff of this file is too big to display
Network access
Supply chain riskThis module accesses the network.
Found 3 instances in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 4 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 3 instances in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 4 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
711947
6.35%79
5.33%11394
0.26%60
-6.25%