atris 3.55.0 → 3.56.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/atris/skills/engines/SKILL.md +11 -3
- package/atris/skills/x-search/SKILL.md +20 -1
- package/atris/skills/youtube/SKILL.md +51 -43
- package/bin/atris.js +119 -87
- package/commands/autopilot-front.js +29 -13
- package/commands/brainstorm.js +77 -476
- package/commands/business.js +13 -1
- package/commands/fleet-report.js +2 -2
- package/commands/human-missions.js +26 -2
- package/commands/init.js +2 -35
- package/commands/integrations.js +266 -0
- package/commands/land.js +53 -23
- package/commands/later.js +52 -0
- package/commands/log.js +79 -30
- package/commands/mission.js +117 -22
- package/commands/next.js +153 -63
- package/commands/now.js +80 -38
- package/commands/recap.js +66 -4
- package/commands/run-front.js +20 -5
- package/commands/spaceship.js +52 -12
- package/commands/status.js +30 -7
- package/commands/task.js +70 -16
- package/commands/terminal.js +5 -5
- package/commands/workflow.js +18 -5
- package/commands/x-search.js +123 -13
- package/commands/youtube.js +639 -36
- package/lib/account-bound.js +7 -0
- package/lib/apply-gate.js +94 -0
- package/lib/context-gatherer.js +55 -8
- package/lib/engine-ask.js +16 -6
- package/lib/first-minute.js +552 -26
- package/lib/known-commands.js +1 -1
- package/lib/runner-command.js +5 -3
- package/lib/scratch-root.js +44 -0
- package/package.json +1 -1
- package/utils/auth.js +9 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: engines
|
|
3
3
|
description: "Dispatch work to an installed terminal agent or named Atris engine profile. Supports Atris Fast, Claude, Codex, Cursor, Fable, Composer, Haiku, Devin, Grok, and Antigravity (agy). Triggers on: use codex, use cursor, use devin, use grok, use agy, use antigravity, use fable, use claude, use atris, engine, dispatch to, worker agent, second opinion build."
|
|
4
|
-
version: 1.4.
|
|
4
|
+
version: 1.4.1
|
|
5
5
|
tags:
|
|
6
6
|
- engines
|
|
7
7
|
- claude
|
|
@@ -28,6 +28,13 @@ One contract, ten live profiles. The orchestrator writes a bounded task prompt,
|
|
|
28
28
|
- build: `atris engine <name> <task-id>`
|
|
29
29
|
- switch: `atris engine <name>`
|
|
30
30
|
|
|
31
|
+
## Fable means Fable
|
|
32
|
+
|
|
33
|
+
Use `atris engine fable "<bounded question>"` for Fable's take. The canonical
|
|
34
|
+
profile pins `claude-fable-5`, gives deep Fable asks ten minutes by default,
|
|
35
|
+
and records the resolved model in the receipt. An explicit `--model` or
|
|
36
|
+
`--timeout` still wins.
|
|
37
|
+
|
|
31
38
|
## Raw binary fallback and debugging
|
|
32
39
|
|
|
33
40
|
Raw spawns are not the default because they skip Atris receipts, watch, and coaching.
|
|
@@ -38,7 +45,7 @@ Raw spawns are not the default because they skip Atris receipts, watch, and coac
|
|
|
38
45
|
| Claude | `claude -p "<prompt>"` | Uses the local Claude configuration. Add `--model opus` for maximum-depth review or `--model sonnet` for speed. |
|
|
39
46
|
| Codex | `codex exec --dangerously-bypass-approvals-and-sandbox -o <result-file> "<prompt>"` (run from the target repo/worktree; read-only research: `--sandbox read-only`) | Headless, exits when done — run it as a tracked background Bash task like the other engines and completion auto-wakes the session. Final answer lands in the `-o` file. Verified live 2026-08-11. Outside a git repo add `--skip-git-repo-check` or it exits 1. ONE-SHOT SESSIONS (`claude -p` workers): run codex in the FOREGROUND and wait — a one-shot session never wakes again, so backgrounding strands the result (observed 2026-08-11). The old plugin path (`codex-companion.mjs task --background`) is deprecated for dispatch: its job store never notifies the session (a finished result sat unread overnight, 2026-08-10) |
|
|
40
47
|
| Cursor | `cursor-agent --trust -p "<prompt>"` (run from the target repo) | Headless print mode; `--trust` required for non-interactive |
|
|
41
|
-
| Fable | `claude -p "<prompt>" --model
|
|
48
|
+
| Fable | `claude -p "<prompt>" --model claude-fable-5` | Raw fallback only. Prefer `atris engine fable` so the model, longer timeout, live log, and receipt stay honest. |
|
|
42
49
|
| Composer | `atris run "<objective>" --engine composer` | Fast navigator/executor profile routed through the installed `ax` binary. |
|
|
43
50
|
| Haiku | `claude -p "<prompt>" --model claude-haiku-4-5` | Fast validation and bounded read-only checks. |
|
|
44
51
|
| Devin | `devin -p --permission-mode dangerous -- "<prompt>"` (run from the target repo) | Default permission mode is read-only for writes — build work NEEDS `--permission-mode dangerous`, so only run it in an isolated worktree. Also `devin cloud` for sessions that outlive this machine. Supports `--model swe-1.7` |
|
|
@@ -65,7 +72,8 @@ Each engine CLI can pin a specific model. Current best picks:
|
|
|
65
72
|
|
|
66
73
|
| Engine | Flag | Best models today |
|
|
67
74
|
|--------|------|-------------------|
|
|
68
|
-
| Claude
|
|
75
|
+
| Claude | `--model opus` | `opus` follows the local Claude alias; use an explicit model identifier for reproducibility |
|
|
76
|
+
| Fable | `--model claude-fable-5` | Canonical Fable 5 route; `atris engine fable` pins it automatically |
|
|
69
77
|
| Devin | `--model swe-1.7` | `swe-1.7` (free right now: use it as the volume executor for parallel bounded slices), `swe-1.7-lightning` for speed |
|
|
70
78
|
| Cursor | `--model cursor-grok-4.6-xhigh` | `cursor-grok-4.6-xhigh` for second-opinion builds, `cursor-grok-4.6-high-fast` for quick pinned asks (answered in ~12s live 2026-08-12), `composer-2.5` for fast edits; parameterized Claude via `'claude-opus-4-8[effort=high]'`; `--list-models` shows the full menu |
|
|
71
79
|
| Composer | `--engine composer` | `composer 2.5` through the Atris profile |
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: x-search
|
|
3
3
|
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."
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.2.0
|
|
5
5
|
tags:
|
|
6
6
|
- x-search
|
|
7
7
|
- social
|
|
@@ -12,6 +12,25 @@ tags:
|
|
|
12
12
|
|
|
13
13
|
> Drop this in `~/.claude/skills/x-search/SKILL.md` and Claude Code becomes your X/Twitter intelligence tool.
|
|
14
14
|
|
|
15
|
+
## Feature map
|
|
16
|
+
|
|
17
|
+
Hard path. Follow in order. Soft memory does not override this.
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
login
|
|
21
|
+
|
|
|
22
|
+
x-search QUERY (5 credits)
|
|
23
|
+
|
|
|
24
|
+
write one Apply (claimable)
|
|
25
|
+
|
|
|
26
|
+
stop
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
1. Login: stored login, then `atris login --agent` if needed. Never paste tokens. Never `/auth/cli`.
|
|
30
|
+
2. Search: `atris x-search "QUERY"`. Always billed (5 credits). Empty or failed search refunds.
|
|
31
|
+
3. One Apply: name a product change plus a receipt that can fail. If missing, the CLI writes a fill-this stub and a next-line. Search still exits 0.
|
|
32
|
+
4. Stop. Empty or failed search does not owe an Apply.
|
|
33
|
+
|
|
15
34
|
## Customer path (preferred)
|
|
16
35
|
|
|
17
36
|
Logged-in customers should use the CLI. Same auth and billing as `atris youtube process` (5 credits).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: youtube
|
|
3
|
-
description: "YouTube discovery and learning.
|
|
4
|
-
version: 2.
|
|
3
|
+
description: "YouTube discovery and learning. Get watch permalinks with atris youtube search QUERY (free, local ytsearch/yt-dlp). On 429 the CLI already retries; use cached rows if printed, else STOP. Never run --paid after a 429. --paid only when the user explicitly asked to buy permalinks (5 credits). After a URL is picked, atris youtube notes URL (free, ephemeral unless --save). atris youtube process only to store knowledge (5 credits). Never paste tokens. Never /auth/cli. Mint with atris login --agent from a stored login. Never summarize a video from model memory. Triggers on: youtube search, find videos, paid youtube search, any youtube.com or youtu.be link, youtube, video, watch this, notes on this."
|
|
4
|
+
version: 2.11.0
|
|
5
5
|
tags:
|
|
6
6
|
- youtube
|
|
7
7
|
- research
|
|
@@ -11,47 +11,56 @@ tags:
|
|
|
11
11
|
|
|
12
12
|
# YouTube Skill
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
## Feature map
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
- **Paid search (5 credits)** → `atris youtube search --paid "<query>"`. Posts `/youtube/search` with the stored token or a youtube-scope agent mint. Prints watch permalinks, titles, and credits. Use this when the customer wants to buy permalinks the same way as `atris x-search`. Do not replace free search with this.
|
|
18
|
-
- **Notes / learning (free)** → `atris youtube notes <url>`. Local captions + a fast engine, about 30 seconds, quotes verified against the transcript. Use when the goal is to learn from a video you already have.
|
|
19
|
-
- **Process / product (5 credits)** → `atris youtube process <url>`. Credits-billed cloud knowledge store. Use when a customer/agent needs the video stored as Atris knowledge.
|
|
16
|
+
Hard path. Follow in order. Soft memory does not override this.
|
|
20
17
|
|
|
21
|
-
|
|
18
|
+
```
|
|
19
|
+
search QUERY (free)
|
|
20
|
+
|
|
|
21
|
+
429 --> CLI already retried once
|
|
22
|
+
--> cached rows printed? use them
|
|
23
|
+
--> rate-limit sentence printed? STOP
|
|
24
|
+
do not run --paid
|
|
25
|
+
|
|
|
26
|
+
pick a URL --> notes URL (free, ephemeral unless --save)
|
|
27
|
+
| --save files the brief + apply stub
|
|
28
|
+
| or teach URL [--section N] (one chapter: claim numbers, named mechanisms, one check; free unless --save)
|
|
29
|
+
|
|
|
30
|
+
write one Apply (claimable) before process
|
|
31
|
+
|
|
|
32
|
+
store knowledge? --> process URL (5 credits)
|
|
33
|
+
|
|
34
|
+
--paid QUERY only if the user asked to buy permalinks
|
|
35
|
+
login: atris login --agent from a stored login
|
|
36
|
+
never paste tokens, never /auth/cli
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
1. Get watch permalinks: `atris youtube search QUERY` (free).
|
|
40
|
+
2. If 429: wait/retry is already in the CLI. If it prints cached rows, use those. If it prints `youtube rate-limited local search. do not use --paid as a fallback; retry later.`, STOP. Do not run `--paid`.
|
|
41
|
+
3. `--paid` only when the user explicitly asked to buy permalinks. The CLI hard-refuses `--paid` when the free cache still has a fresh same-query hit.
|
|
42
|
+
4. `atris youtube notes URL` after a URL is picked (free). Notes is ephemeral unless `--save`.
|
|
43
|
+
5. Write one Apply (change + receipt) before `atris youtube process`. Process still requires a filled Apply (so you `--save`, fill Apply, then process).
|
|
44
|
+
6. Never paste tokens. Never `/auth/cli`. Mint with `atris login --agent` from a stored login.
|
|
45
|
+
|
|
46
|
+
If the user says "find videos", "search youtube", or "get youtube links" → search. If they say "learn from", "notes on", "alpha", or "rabbit hole" → notes. If they say "process", "store", "add to knowledge" → process. "Buy permalinks" or "paid search" is the only ask that unlocks `--paid`.
|
|
22
47
|
|
|
23
48
|
Never summarize a video from model memory; that is fabrication.
|
|
24
49
|
|
|
25
|
-
## Bootstrap
|
|
50
|
+
## Bootstrap
|
|
51
|
+
|
|
52
|
+
Search and notes need no login. Paid search and process need a stored login, then `atris login --agent`. Never print credentials. Never `/auth/cli`.
|
|
26
53
|
|
|
27
54
|
```bash
|
|
28
55
|
#!/bin/bash
|
|
29
56
|
set -e
|
|
30
57
|
|
|
31
|
-
# 1. Check atris CLI
|
|
32
58
|
if ! command -v atris &> /dev/null; then
|
|
33
59
|
echo "Installing atris CLI..."
|
|
34
60
|
npm install -g atris
|
|
35
61
|
fi
|
|
36
62
|
|
|
37
|
-
|
|
38
|
-
if [ ! -f ~/.atris/credentials.json ]; then
|
|
39
|
-
echo "Not logged in. Search and notes still work. Process needs: atris login"
|
|
40
|
-
fi
|
|
41
|
-
|
|
42
|
-
# 3. Extract token when present
|
|
43
|
-
if [ -f ~/.atris/credentials.json ]; then
|
|
44
|
-
if command -v node &> /dev/null; then
|
|
45
|
-
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
|
|
46
|
-
elif command -v python3 &> /dev/null; then
|
|
47
|
-
TOKEN=$(python3 -c "import json,os; print(json.load(open(os.path.expanduser('~/.atris/credentials.json')))['token'])")
|
|
48
|
-
elif command -v jq &> /dev/null; then
|
|
49
|
-
TOKEN=$(jq -r '.token' ~/.atris/credentials.json)
|
|
50
|
-
fi
|
|
51
|
-
export ATRIS_TOKEN="$TOKEN"
|
|
52
|
-
fi
|
|
53
|
-
|
|
54
|
-
echo "Ready. YouTube skill active (search + notes free; process 5 credits)."
|
|
63
|
+
echo "Ready. Feature map: free search, 429 cache-or-stop, notes, then process."
|
|
55
64
|
```
|
|
56
65
|
|
|
57
66
|
---
|
|
@@ -66,14 +75,18 @@ atris youtube search "MCP agents" --json
|
|
|
66
75
|
|
|
67
76
|
Uses `ytsearch` on PATH when present, else bundled `scripts/det/ytsearch`, else `yt-dlp --flat-playlist --print` with `ytsearchN:`. No credits. No `/agent/process_youtube` call.
|
|
68
77
|
|
|
69
|
-
|
|
78
|
+
On 429 the CLI retries once, then serves `~/.atris/youtube-search-cache.json` if the same query is younger than one hour. If it prints the rate-limit sentence, stop. Do not run `--paid`.
|
|
79
|
+
|
|
80
|
+
## Paid search (5 credits, opt-in buy only)
|
|
81
|
+
|
|
82
|
+
Only when the user explicitly asked to buy permalinks. A 429 or a missing cache is not that ask.
|
|
70
83
|
|
|
71
84
|
```bash
|
|
72
85
|
atris youtube search --paid "MCP agents 2026"
|
|
73
86
|
atris youtube search --paid "MCP agents" --limit 10
|
|
74
87
|
```
|
|
75
88
|
|
|
76
|
-
Requires login
|
|
89
|
+
Requires a stored login, then `atris login --agent`. The CLI mints a youtube-scope agent token from disk the same way as `atris youtube process` and `atris x-search`. Never `/auth/cli`. Never paste tokens. Prints `title | watch permalink` plus credits. Empty or failed searches refund.
|
|
77
90
|
|
|
78
91
|
Line contract:
|
|
79
92
|
|
|
@@ -90,10 +103,7 @@ title | channel | duration | views | upload_date | https://youtu.be/ID
|
|
|
90
103
|
Base: `https://api.atris.ai/api`
|
|
91
104
|
Auth: `-H "Authorization: Bearer $TOKEN"`
|
|
92
105
|
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
|
|
96
|
-
```
|
|
106
|
+
Do not extract or paste tokens. The CLI reads the stored login. Agents mint with `atris login --agent`.
|
|
97
107
|
|
|
98
108
|
### Process a Video
|
|
99
109
|
```bash
|
|
@@ -203,7 +213,7 @@ Two layers, never mixed. The reply the person reads is flowing prose: ideas, spe
|
|
|
203
213
|
|
|
204
214
|
`atris youtube search` shells to local ytsearch/yt-dlp and never hits the Atris API.
|
|
205
215
|
|
|
206
|
-
`atris youtube search --paid` posts `{query, limit}` to `/youtube/search` with bearer auth. Agent tokens need the youtube scope.
|
|
216
|
+
`atris youtube search --paid` posts `{query, limit}` to `/youtube/search` with bearer auth. Agent tokens need the youtube scope. This is an opt-in buy, not a 429 fallback.
|
|
207
217
|
|
|
208
218
|
`atris youtube` process first tries local transcript extraction with `yt-dlp`. It sends timestamped `transcript_text` to `/agent/process_youtube` with `cache_transcript=false`. If local transcript processing fails with a retryable error, it falls back to cloud video processing. Use `--json` to inspect `metadata.processing_method` and `metadata.transcript_source`.
|
|
209
219
|
|
|
@@ -225,35 +235,33 @@ Two layers, never mixed. The reply the person reads is flowing prose: ideas, spe
|
|
|
225
235
|
|
|
226
236
|
| Error | Meaning | Fix |
|
|
227
237
|
|-------|---------|-----|
|
|
228
|
-
| `401` | Token expired/invalid | `atris login --
|
|
238
|
+
| `401` | Token expired/invalid | `atris login --agent` from a stored login |
|
|
229
239
|
| `402` | Not enough credits | Check balance, purchase at atris.ai |
|
|
230
240
|
| `400` | Invalid YouTube URL | Check URL format |
|
|
231
241
|
| `502` | Transcript or cloud processing failed | Retry; credits auto-refunded when backend fails |
|
|
232
242
|
| search exit 2 | ytsearch/yt-dlp missing or no results | Install yt-dlp, or put ytsearch on PATH |
|
|
233
|
-
| search 429 | YouTube rate-limited local search |
|
|
243
|
+
| search 429 | YouTube rate-limited local search | CLI already retried; use cached rows if printed; if the rate-limit sentence prints, STOP; do not use --paid |
|
|
234
244
|
|
|
235
245
|
---
|
|
236
246
|
|
|
237
247
|
## Quick Reference
|
|
238
248
|
|
|
239
249
|
```bash
|
|
240
|
-
# Setup
|
|
250
|
+
# Setup: human stores a login, then agents mint. never /auth/cli
|
|
241
251
|
npm install -g atris && atris login
|
|
252
|
+
atris login --agent
|
|
242
253
|
|
|
243
254
|
# Free: discover videos
|
|
244
255
|
atris youtube search "MCP agents 2026"
|
|
245
256
|
atris youtube search "MCP agents" --limit 10
|
|
246
257
|
|
|
247
|
-
# Paid:
|
|
258
|
+
# Paid: only if the user asked to buy permalinks (5 credits). never a 429 fallback
|
|
248
259
|
atris youtube search --paid "MCP agents 2026"
|
|
249
260
|
|
|
250
261
|
# Free: notes on a URL you already have
|
|
251
262
|
atris youtube notes "https://youtu.be/VIDEO_ID"
|
|
252
263
|
|
|
253
|
-
#
|
|
254
|
-
TOKEN=$(node -e "console.log(require('$HOME/.atris/credentials.json').token)")
|
|
255
|
-
|
|
256
|
-
# Process a video (5 credits)
|
|
264
|
+
# Process a video (5 credits). different store from paid search
|
|
257
265
|
atris youtube process "https://youtube.com/watch?v=..." --query "Create a outline (flowing, idea-first) and action brief"
|
|
258
266
|
|
|
259
267
|
# Process + store to agent knowledge
|
package/bin/atris.js
CHANGED
|
@@ -47,7 +47,7 @@ const {
|
|
|
47
47
|
requireAccountBound,
|
|
48
48
|
refuseAccountGlobal,
|
|
49
49
|
} = require('../lib/account-bound');
|
|
50
|
-
const { isHelpToken, argsWantHelp } = require('../lib/noninteractive');
|
|
50
|
+
const { isHelpToken, argsWantHelp, hasYesFlag } = require('../lib/noninteractive');
|
|
51
51
|
|
|
52
52
|
// State detection for smart default
|
|
53
53
|
const { detectWorkspaceState, loadContext } = require('../lib/state-detection');
|
|
@@ -56,12 +56,20 @@ const {
|
|
|
56
56
|
createStarterTask,
|
|
57
57
|
shouldGatherContext,
|
|
58
58
|
isAtrisMetaQuestion,
|
|
59
|
+
isFlagLikeAnswer,
|
|
59
60
|
renderPrompt: renderContextGathererPrompt,
|
|
60
61
|
} = require('../lib/context-gatherer');
|
|
61
62
|
const {
|
|
62
63
|
buildFirstMinute,
|
|
64
|
+
firstTalkJson,
|
|
65
|
+
folderName,
|
|
63
66
|
freshMinuteJson,
|
|
64
67
|
isBareAtrisFlag,
|
|
68
|
+
isFirstTalkLine,
|
|
69
|
+
isLeftoverVerbLook,
|
|
70
|
+
listUserVisibleWork,
|
|
71
|
+
personName,
|
|
72
|
+
renderFirstTalk,
|
|
65
73
|
shouldAutoInitFresh,
|
|
66
74
|
} = require('../lib/first-minute');
|
|
67
75
|
|
|
@@ -484,17 +492,14 @@ function showStartHelp() {
|
|
|
484
492
|
}
|
|
485
493
|
|
|
486
494
|
function showHelpShort() {
|
|
487
|
-
console.log('atris: you say what you want
|
|
488
|
-
console.log('');
|
|
489
|
-
console.log('
|
|
490
|
-
console.log(' atris
|
|
491
|
-
console.log(' atris
|
|
492
|
-
console.log(' atris
|
|
493
|
-
console.log(' atris
|
|
494
|
-
console.log(' atris
|
|
495
|
-
console.log(' atris review validate');
|
|
496
|
-
console.log(' atris recap spoken recap of what landed');
|
|
497
|
-
console.log(' atris mission status active goals + next move');
|
|
495
|
+
console.log('atris: you say what you want. already won. one next step.');
|
|
496
|
+
console.log('');
|
|
497
|
+
console.log(' atris "what do you want here?" empty folder');
|
|
498
|
+
console.log(' atris later "..." remember without a room');
|
|
499
|
+
console.log(' atris do work already here');
|
|
500
|
+
console.log(' atris spaceship Keep working for a few hours');
|
|
501
|
+
console.log(' atris autopilot Keep working until you stop');
|
|
502
|
+
console.log(' atris mission the one goal');
|
|
498
503
|
console.log('');
|
|
499
504
|
console.log('More: atris help --all · machine list: atris help --json');
|
|
500
505
|
}
|
|
@@ -506,7 +511,7 @@ function helpCatalog() {
|
|
|
506
511
|
{ name: 'review', summary: 'validate work and capture learnings', json: false, interactive_risk: 'low' },
|
|
507
512
|
{ name: 'recap', summary: 'spoken recap of what your team did', json: true, interactive_risk: 'low' },
|
|
508
513
|
{ name: 'mission', summary: 'durable goal + owner + verifier + tick', json: true, interactive_risk: 'medium' },
|
|
509
|
-
{ name: 'log', summary: 'append an idea to today inbox (or --repl)', json:
|
|
514
|
+
{ name: 'log', summary: 'append an idea to today inbox (or --repl)', json: true, interactive_risk: 'low' },
|
|
510
515
|
{ name: 'wish', summary: 'headless inbox / mission intake', json: true, interactive_risk: 'low' },
|
|
511
516
|
{ name: 'learn', summary: 'structured project learnings', json: false, interactive_risk: 'low' },
|
|
512
517
|
{ name: 'activate', summary: 'load atris context for this session', json: false, interactive_risk: 'low' },
|
|
@@ -517,38 +522,16 @@ function helpCatalog() {
|
|
|
517
522
|
}
|
|
518
523
|
|
|
519
524
|
function showHelpAll() {
|
|
525
|
+
console.log('you say what you want. already won. one next step.');
|
|
520
526
|
console.log('');
|
|
521
|
-
console.log('
|
|
522
|
-
console.log('atris');
|
|
523
|
-
console.log('
|
|
524
|
-
console.log('
|
|
525
|
-
console.log('');
|
|
526
|
-
console.log('
|
|
527
|
-
console.log('');
|
|
528
|
-
console.log('
|
|
529
|
-
console.log(' npx atris same after a local install');
|
|
530
|
-
console.log(' 2. say what you want built, checked, or researched');
|
|
531
|
-
console.log(' 3. atris files the work, then you review');
|
|
532
|
-
console.log('');
|
|
533
|
-
console.log('Common invocations:');
|
|
534
|
-
console.log(' atris "<request>" one isolated change, then Review');
|
|
535
|
-
console.log(' atris "<request>" --verify "<cmd>" --json');
|
|
536
|
-
console.log(' atris init [--yes] scaffold this project');
|
|
537
|
-
console.log(' npx atris init [--yes] same after a local install');
|
|
538
|
-
console.log(' atris mission status current mission + next move');
|
|
539
|
-
console.log(' atris task ready <id> --proof "..."');
|
|
540
|
-
console.log(' atris computer');
|
|
541
|
-
console.log(' atris engine validate latest');
|
|
542
|
-
console.log(' atris playbook workspace style rules and paired trials');
|
|
543
|
-
console.log(' atris business init "My Company"');
|
|
544
|
-
console.log(' atris run');
|
|
545
|
-
console.log(' atris drill');
|
|
546
|
-
console.log(' atris status');
|
|
547
|
-
console.log(' atris soul');
|
|
548
|
-
console.log(' atris fleet status');
|
|
549
|
-
console.log(' ask/stop/ready see atris mission and atris task ready');
|
|
550
|
-
console.log('');
|
|
551
|
-
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
527
|
+
console.log(' atris later "..." remember without a room');
|
|
528
|
+
console.log(' atris do work already here');
|
|
529
|
+
console.log(' atris spaceship Keep working for a few hours');
|
|
530
|
+
console.log(' atris autopilot Keep working until you stop');
|
|
531
|
+
console.log(' atris mission the one goal');
|
|
532
|
+
console.log(' atris recap what got done');
|
|
533
|
+
console.log(' atris review check the work');
|
|
534
|
+
console.log(' atris stop stop the live goal');
|
|
552
535
|
console.log('');
|
|
553
536
|
console.log('Atris Computers:');
|
|
554
537
|
console.log(' Owner = User | Business');
|
|
@@ -765,7 +748,7 @@ function showHelpAll() {
|
|
|
765
748
|
console.log('');
|
|
766
749
|
console.log('Other:');
|
|
767
750
|
console.log(' version - Show Atris version');
|
|
768
|
-
console.log(' help -
|
|
751
|
+
console.log(' help - you say what you want (help --all for every command)');
|
|
769
752
|
console.log('');
|
|
770
753
|
console.log('Tip: Just run "atris" to get started');
|
|
771
754
|
console.log('');
|
|
@@ -1344,13 +1327,13 @@ function printFirstUseNext() {
|
|
|
1344
1327
|
console.log(`Then: ${firstUseCommand()}`);
|
|
1345
1328
|
}
|
|
1346
1329
|
|
|
1347
|
-
function runMinimalInit() {
|
|
1330
|
+
function runMinimalInit({ silent = false } = {}) {
|
|
1348
1331
|
const script = process.argv[1] || path.join(__dirname, 'atris.js');
|
|
1349
1332
|
const result = spawnSync(process.execPath, [script, 'init', '--minimal', '--yes'], {
|
|
1350
1333
|
cwd: process.cwd(),
|
|
1351
1334
|
env: process.env,
|
|
1352
1335
|
encoding: 'utf8',
|
|
1353
|
-
stdio: 'inherit',
|
|
1336
|
+
stdio: silent ? ['ignore', 'pipe', 'pipe'] : 'inherit',
|
|
1354
1337
|
});
|
|
1355
1338
|
return Number.isInteger(result.status) ? result.status : 1;
|
|
1356
1339
|
}
|
|
@@ -1366,16 +1349,56 @@ async function interactiveEntry(userInput, options = {}) {
|
|
|
1366
1349
|
const workspaceDir = process.cwd();
|
|
1367
1350
|
const state = detectWorkspaceState(workspaceDir);
|
|
1368
1351
|
|
|
1369
|
-
// Fresh folder is
|
|
1352
|
+
// Fresh folder is a conversation, not a scaffold form.
|
|
1370
1353
|
if (state.state === 'fresh') {
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1354
|
+
const request = String(userInput || '').trim();
|
|
1355
|
+
const room = folderName(workspaceDir);
|
|
1356
|
+
const who = personName();
|
|
1357
|
+
if (!request) {
|
|
1358
|
+
if (options.asJson) {
|
|
1359
|
+
console.log(JSON.stringify(freshMinuteJson(room, listUserVisibleWork(workspaceDir), { root: workspaceDir }), null, 2));
|
|
1360
|
+
return 2;
|
|
1361
|
+
}
|
|
1362
|
+
if (shouldAutoInitFresh(process.argv.slice(2))) {
|
|
1363
|
+
return runMinimalInit();
|
|
1364
|
+
}
|
|
1365
|
+
printFirstMinuteScreen({ root: workspaceDir, fresh: true });
|
|
1366
|
+
return 0;
|
|
1374
1367
|
}
|
|
1375
|
-
if (
|
|
1376
|
-
|
|
1368
|
+
if (isLeftoverVerbLook(request)) {
|
|
1369
|
+
if (options.asJson) {
|
|
1370
|
+
console.log(JSON.stringify(freshMinuteJson(room, listUserVisibleWork(workspaceDir), { root: workspaceDir }), null, 2));
|
|
1371
|
+
return 2;
|
|
1372
|
+
}
|
|
1373
|
+
printFirstMinuteScreen({ root: workspaceDir, fresh: true });
|
|
1374
|
+
return 0;
|
|
1377
1375
|
}
|
|
1378
|
-
|
|
1376
|
+
if (!isFirstTalkLine(request) && isAtrisMetaQuestion(request)) {
|
|
1377
|
+
if (options.asJson) {
|
|
1378
|
+
console.log(JSON.stringify({
|
|
1379
|
+
schema: 'atris.overview.v1',
|
|
1380
|
+
ok: true,
|
|
1381
|
+
product: 'Atris',
|
|
1382
|
+
}, null, 2));
|
|
1383
|
+
return 0;
|
|
1384
|
+
}
|
|
1385
|
+
printAtrisOverview();
|
|
1386
|
+
return 0;
|
|
1387
|
+
}
|
|
1388
|
+
if (isFlagLikeAnswer(request)) {
|
|
1389
|
+
printFirstMinuteScreen({ root: workspaceDir, fresh: true });
|
|
1390
|
+
return 0;
|
|
1391
|
+
}
|
|
1392
|
+
const initStatus = runMinimalInit({ silent: true });
|
|
1393
|
+
if (initStatus !== 0) return initStatus;
|
|
1394
|
+
saveContextProfile(workspaceDir, request, { source: 'first_talk' });
|
|
1395
|
+
const starter = createStarterTask(workspaceDir, request);
|
|
1396
|
+
if (options.asJson) {
|
|
1397
|
+
console.log(JSON.stringify(firstTalkJson({ starter, person: who, folder: room }), null, 2));
|
|
1398
|
+
return 0;
|
|
1399
|
+
}
|
|
1400
|
+
console.log('');
|
|
1401
|
+
console.log(renderFirstTalk({ person: who, folder: room, starter }));
|
|
1379
1402
|
return 0;
|
|
1380
1403
|
}
|
|
1381
1404
|
|
|
@@ -1921,18 +1944,14 @@ if (command === 'init') {
|
|
|
1921
1944
|
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
1922
1945
|
} else if (command === 'land') {
|
|
1923
1946
|
// landCommand can throw synchronously on empty repos; wrap so callers get a
|
|
1924
|
-
// one-line
|
|
1947
|
+
// one-line sentence instead of an uncaught stack from Promise.resolve(fn()).
|
|
1925
1948
|
Promise.resolve()
|
|
1926
1949
|
.then(() => require('../commands/land').landCommand(process.argv.slice(3)))
|
|
1927
|
-
.then((code) => process.exit(code
|
|
1950
|
+
.then((code) => process.exit(typeof code === 'number' ? code : 0))
|
|
1928
1951
|
.catch((err) => {
|
|
1929
|
-
const msg = String(err && err.message || err || '');
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
} else {
|
|
1933
|
-
console.error(`land: ${msg}`);
|
|
1934
|
-
}
|
|
1935
|
-
process.exit(1);
|
|
1952
|
+
const msg = String(err && err.message || err || 'land could not run').split('\n')[0];
|
|
1953
|
+
console.log(msg);
|
|
1954
|
+
process.exit(2);
|
|
1936
1955
|
});
|
|
1937
1956
|
} else if (command === 'caretaker') {
|
|
1938
1957
|
Promise.resolve(require('../commands/caretaker').caretakerCommand(process.argv.slice(3)))
|
|
@@ -2035,7 +2054,6 @@ if (command === 'init') {
|
|
|
2035
2054
|
} else if (command === 'log') {
|
|
2036
2055
|
const logArgs = process.argv.slice(3);
|
|
2037
2056
|
const subcommand = logArgs[0];
|
|
2038
|
-
const positional = logArgs.filter((arg) => !String(arg).startsWith('-'));
|
|
2039
2057
|
if (subcommand === 'sync') {
|
|
2040
2058
|
require('../commands/log-sync').logSyncAtris()
|
|
2041
2059
|
.then(() => process.exit(0))
|
|
@@ -2044,24 +2062,16 @@ if (command === 'init') {
|
|
|
2044
2062
|
process.exit(1);
|
|
2045
2063
|
});
|
|
2046
2064
|
} else if (subcommand === '--help' || subcommand === '-h' || subcommand === 'help') {
|
|
2047
|
-
console.log('Usage: atris log ["note"] | --repl | sync |
|
|
2065
|
+
console.log('Usage: atris log ["note"] [--json] | --repl | sync | help');
|
|
2048
2066
|
console.log('');
|
|
2049
2067
|
console.log(' atris log "an idea" Append a note to today\'s ## Inbox');
|
|
2068
|
+
console.log(' atris log text One word still lands in Inbox. No live business required');
|
|
2069
|
+
console.log(' atris log "an idea" --json');
|
|
2050
2070
|
console.log(' atris log --repl Open today\'s journal REPL');
|
|
2051
2071
|
console.log(' atris log Open the REPL (needs a terminal)');
|
|
2052
2072
|
console.log(' atris log sync Sync the local journal to cloud');
|
|
2053
|
-
console.log(' atris log <slug> Show business log history (single slug token)');
|
|
2054
2073
|
console.log(' atris wish "..." Headless inbox write; add --json --no-mission for agents');
|
|
2055
2074
|
process.exit(0);
|
|
2056
|
-
} else if (
|
|
2057
|
-
positional.length === 1
|
|
2058
|
-
&& !logArgs.includes('--repl')
|
|
2059
|
-
&& /^[a-z0-9][a-z0-9_-]{0,63}$/i.test(positional[0])
|
|
2060
|
-
) {
|
|
2061
|
-
// Business log: atris log <business-slug> (single slug token only)
|
|
2062
|
-
require('../commands/context-sync').businessLog(positional[0])
|
|
2063
|
-
.then(() => process.exit(0))
|
|
2064
|
-
.catch((err) => { console.error(`\n✗ Error: ${err.message || err}`); process.exit(1); });
|
|
2065
2075
|
} else {
|
|
2066
2076
|
logCmd();
|
|
2067
2077
|
}
|
|
@@ -2084,13 +2094,14 @@ if (command === 'init') {
|
|
|
2084
2094
|
}
|
|
2085
2095
|
} else if (command === 'now') {
|
|
2086
2096
|
const args = process.argv.slice(3);
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
process.exit(0);
|
|
2090
|
-
}
|
|
2091
|
-
require('../commands/now').nowAtris(args);
|
|
2097
|
+
const nowCode = require('../commands/now').nowAtris(args);
|
|
2098
|
+
process.exit(Number.isInteger(nowCode) ? nowCode : 0);
|
|
2092
2099
|
} else if (command === 'recap') {
|
|
2093
|
-
require('../commands/recap').recapAtris(process.argv.slice(3));
|
|
2100
|
+
const recapCode = require('../commands/recap').recapAtris(process.argv.slice(3));
|
|
2101
|
+
if (Number.isInteger(recapCode)) process.exit(recapCode);
|
|
2102
|
+
} else if (command === 'later') {
|
|
2103
|
+
const laterCode = require('../commands/later').laterAtris(process.argv.slice(3));
|
|
2104
|
+
process.exit(Number.isInteger(laterCode) ? laterCode : 0);
|
|
2094
2105
|
} else if (command === 'activate') {
|
|
2095
2106
|
const args = process.argv.slice(3);
|
|
2096
2107
|
if (args.includes('--help') || args.includes('-h') || args[0] === 'help') {
|
|
@@ -2463,7 +2474,21 @@ if (command === 'init') {
|
|
|
2463
2474
|
process.exit(code);
|
|
2464
2475
|
} else if (command === 'autopilot') {
|
|
2465
2476
|
const args = process.argv.slice(3);
|
|
2466
|
-
|
|
2477
|
+
const { isUnboundScratchFolder, refuseUnboundScratch } = require('../lib/scratch-root');
|
|
2478
|
+
const { resolveWorkspaceRoot } = require('../lib/mission-root');
|
|
2479
|
+
const autopilotRoot = resolveWorkspaceRoot(process.cwd());
|
|
2480
|
+
const autopilotHelp = argsWantHelp(args) || args[0] === 'help';
|
|
2481
|
+
const autopilotControl = args[0] === 'stop' || args[0] === 'status';
|
|
2482
|
+
const autopilotJsonPlan = args.includes('--json') && !args.includes('--yes') && !args.includes('-y');
|
|
2483
|
+
const autopilotTalkOnly = !hasYesFlag(args) && !args.includes('--auto') && !args.includes('--legacy');
|
|
2484
|
+
// applyRunnerFlags seeds .atris/state/engines.json. Help, stop/status, JSON
|
|
2485
|
+
// plan, and an unbound scratch talk must not mint a room. --yes is not an unlock.
|
|
2486
|
+
if (!autopilotHelp && !autopilotControl && !autopilotJsonPlan && !autopilotTalkOnly && isUnboundScratchFolder(autopilotRoot)) {
|
|
2487
|
+
process.exit(refuseUnboundScratch());
|
|
2488
|
+
}
|
|
2489
|
+
if (!autopilotHelp && !isUnboundScratchFolder(autopilotRoot)) {
|
|
2490
|
+
applyRunnerFlags(args);
|
|
2491
|
+
}
|
|
2467
2492
|
|
|
2468
2493
|
if (args.includes('--legacy')) {
|
|
2469
2494
|
const legacyArgs = args.filter(a => a !== '--legacy');
|
|
@@ -2739,8 +2764,9 @@ if (command === 'init') {
|
|
|
2739
2764
|
const raw = process.argv.slice(3);
|
|
2740
2765
|
const { gmailCommand, extractGmailMailboxAccount } = require('../commands/integrations');
|
|
2741
2766
|
const mailbox = extractGmailMailboxAccount(raw);
|
|
2742
|
-
|
|
2743
|
-
|
|
2767
|
+
// Mailbox --account <id> is a selector, not the workspace opt-in.
|
|
2768
|
+
// Scratch folders refuse every gmail verb the same way as slack/inbox.
|
|
2769
|
+
const gate = requireAccountBound(mailbox.args.filter((arg) => arg !== '--account'));
|
|
2744
2770
|
if (!gate.ok) {
|
|
2745
2771
|
process.exit(refuseAccountGlobal());
|
|
2746
2772
|
return;
|
|
@@ -2775,9 +2801,15 @@ if (command === 'init') {
|
|
|
2775
2801
|
} else if (command === 'slack') {
|
|
2776
2802
|
{
|
|
2777
2803
|
const raw = process.argv.slice(3);
|
|
2778
|
-
const
|
|
2779
|
-
|
|
2780
|
-
|
|
2804
|
+
const { slackCommand, extractGmailMailboxAccount } = require('../commands/integrations');
|
|
2805
|
+
const account = extractGmailMailboxAccount(raw);
|
|
2806
|
+
// Account --account <id> is a selector, not the workspace opt-in.
|
|
2807
|
+
// Scratch folders refuse every slack verb the same way as gmail/inbox.
|
|
2808
|
+
const gate = requireAccountBound(account.args.filter((arg) => arg !== '--account'));
|
|
2809
|
+
if (!gate.ok) {
|
|
2810
|
+
process.exit(refuseAccountGlobal());
|
|
2811
|
+
return;
|
|
2812
|
+
}
|
|
2781
2813
|
const subcommand = gate.args[0];
|
|
2782
2814
|
const args = gate.args.slice(1);
|
|
2783
2815
|
slackCommand(subcommand, ...args)
|