You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

atris

Package Overview
Dependencies
Maintainers
1
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

atris - npm Package Compare versions

Comparing version
2.3.5
to
2.3.7
+716
atris/atrisDev.md
# 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.
+1
-1
---
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);

@@ -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 @@ }

@@ -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 {

@@ -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);

@@ -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 @@ }

@@ -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
};
{
"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",

@@ -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);

@@ -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