@agentwhy/cli 0.0.0-dev
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/LICENSE +202 -0
- package/NOTICE +2 -0
- package/README.md +181 -0
- package/THIRD_PARTY_NOTICES.md +31 -0
- package/dist/adapter/claude-code/contract/assumptions.js +208 -0
- package/dist/adapter/claude-code/contract/denials.js +15 -0
- package/dist/adapter/claude-code/contract/entry-points.js +15 -0
- package/dist/adapter/claude-code/contract/fields.js +73 -0
- package/dist/adapter/claude-code/contract/hooks.js +96 -0
- package/dist/adapter/claude-code/contract/identifiers.js +15 -0
- package/dist/adapter/claude-code/contract/layout.js +29 -0
- package/dist/adapter/claude-code/contract/line-types.js +26 -0
- package/dist/adapter/claude-code/contract/projects.js +23 -0
- package/dist/adapter/claude-code/contract/recognition.js +14 -0
- package/dist/adapter/claude-code/contract/session-title.js +20 -0
- package/dist/adapter/claude-code/contract/settings.js +27 -0
- package/dist/adapter/claude-code/contract/task-notifications.js +33 -0
- package/dist/adapter/claude-code/contract/tools.js +37 -0
- package/dist/adapter/claude-code/contract/version.js +51 -0
- package/dist/adapter/claude-code/discovery/claude-code-project-catalogue.js +129 -0
- package/dist/adapter/claude-code/discovery/claude-code-recognition.js +46 -0
- package/dist/adapter/claude-code/discovery/claude-code-session-catalogue.js +100 -0
- package/dist/adapter/claude-code/discovery/claude-code-session-discovery.js +61 -0
- package/dist/adapter/claude-code/discovery/claude-code-session-titles.js +28 -0
- package/dist/adapter/claude-code/discovery/discovered-session.js +1 -0
- package/dist/adapter/claude-code/discovery/session-entries.js +41 -0
- package/dist/adapter/claude-code/discovery/transcript-tail.js +81 -0
- package/dist/adapter/claude-code/events/claude-code-session-source.js +197 -0
- package/dist/adapter/claude-code/events/delegation-index.js +15 -0
- package/dist/adapter/claude-code/events/transcript-scan.js +179 -0
- package/dist/adapter/claude-code/hooks/hook-output.js +42 -0
- package/dist/adapter/claude-code/hooks/pre-tool-use-input.js +23 -0
- package/dist/adapter/claude-code/hooks/stop-input.js +25 -0
- package/dist/adapter/claude-code/hooks/subagent-stop-input.js +26 -0
- package/dist/adapter/claude-code/policy/deny-rules.js +46 -0
- package/dist/adapter/claude-code/probe/claude-code-probe.js +86 -0
- package/dist/adapter/claude-code/probe/collectors/agent-tool-input-key-collector.js +24 -0
- package/dist/adapter/claude-code/probe/collectors/denial-kind-collector.js +20 -0
- package/dist/adapter/claude-code/probe/collectors/denied-call-collector.js +11 -0
- package/dist/adapter/claude-code/probe/collectors/identifier-collector.js +19 -0
- package/dist/adapter/claude-code/probe/collectors/line-collector.js +1 -0
- package/dist/adapter/claude-code/probe/collectors/line-type-collector.js +29 -0
- package/dist/adapter/claude-code/probe/collectors/sidechain-collector.js +20 -0
- package/dist/adapter/claude-code/probe/collectors/task-notification-collector.js +51 -0
- package/dist/adapter/claude-code/probe/collectors/tool-result-reference-collector.js +31 -0
- package/dist/adapter/claude-code/probe/collectors/tool-use-collector.js +24 -0
- package/dist/adapter/claude-code/probe/collectors/tool-version-collector.js +14 -0
- package/dist/adapter/claude-code/probe/collectors/top-level-key-collector.js +14 -0
- package/dist/adapter/claude-code/probe/collectors/unknown-line-type-key-collector.js +24 -0
- package/dist/adapter/claude-code/probe/collectors/working-directory-collector.js +28 -0
- package/dist/adapter/claude-code/probe/doctor-report.js +1 -0
- package/dist/adapter/claude-code/probe/meta-tally.js +42 -0
- package/dist/adapter/claude-code/probe/session-probe.js +1 -0
- package/dist/adapter/claude-code/probe/session-tally.js +41 -0
- package/dist/adapter/claude-code/probe/transcript-line.js +30 -0
- package/dist/adapter/claude-code/probe/transcript-tally.js +74 -0
- package/dist/adapter/claude-code/settings/deny-entries.js +65 -0
- package/dist/adapter/claude-code/settings/hook-entries.js +303 -0
- package/dist/adapter/codex/contract/actions.js +69 -0
- package/dist/adapter/codex/contract/assumptions.js +55 -0
- package/dist/adapter/codex/contract/capabilities.js +24 -0
- package/dist/adapter/codex/contract/delegations.js +30 -0
- package/dist/adapter/codex/contract/deliveries.js +25 -0
- package/dist/adapter/codex/contract/envelope.js +33 -0
- package/dist/adapter/codex/contract/hook-refusals.js +14 -0
- package/dist/adapter/codex/contract/hooks.js +46 -0
- package/dist/adapter/codex/contract/messages.js +47 -0
- package/dist/adapter/codex/contract/permissions.js +27 -0
- package/dist/adapter/codex/contract/reviews.js +13 -0
- package/dist/adapter/codex/contract/session.js +31 -0
- package/dist/adapter/codex/contract/turns.js +23 -0
- package/dist/adapter/codex/contract/version.js +15 -0
- package/dist/adapter/codex/discovery/codex-conversations.js +44 -0
- package/dist/adapter/codex/discovery/codex-project-catalogue.js +49 -0
- package/dist/adapter/codex/discovery/codex-recognition.js +20 -0
- package/dist/adapter/codex/discovery/codex-session-catalogue.js +28 -0
- package/dist/adapter/codex/discovery/codex-session-discovery.js +115 -0
- package/dist/adapter/codex/discovery/codex-session-index.js +21 -0
- package/dist/adapter/codex/discovery/codex-session-titles.js +135 -0
- package/dist/adapter/codex/discovery/session-header.js +86 -0
- package/dist/adapter/codex/discovery/session-owners.js +11 -0
- package/dist/adapter/codex/discovery/session-roots.js +49 -0
- package/dist/adapter/codex/events/action-items.js +138 -0
- package/dist/adapter/codex/events/capability-records.js +26 -0
- package/dist/adapter/codex/events/codex-session-source.js +121 -0
- package/dist/adapter/codex/events/hook-refusals.js +27 -0
- package/dist/adapter/codex/events/rollout-scan.js +614 -0
- package/dist/adapter/codex/events/turn-permissions.js +60 -0
- package/dist/adapter/codex/hooks/pre-tool-use-input.js +24 -0
- package/dist/adapter/codex/hooks/stop-refusals.js +57 -0
- package/dist/adapter/codex/probe/codex-doctor-report.js +1 -0
- package/dist/adapter/codex/probe/codex-probe.js +268 -0
- package/dist/adapter/codex/settings/codex-hooks.js +83 -0
- package/dist/cli/cli-command.js +1 -0
- package/dist/cli/command-router.js +42 -0
- package/dist/cli/commands/check-cli-command.js +128 -0
- package/dist/cli/commands/codex-stop-cli-command.js +27 -0
- package/dist/cli/commands/doctor-arguments.js +32 -0
- package/dist/cli/commands/doctor-cli-command.js +31 -0
- package/dist/cli/commands/doctor-usage.js +14 -0
- package/dist/cli/commands/init-cli-command.js +123 -0
- package/dist/cli/commands/menu-cli-command.js +58 -0
- package/dist/cli/commands/notify-cli-command.js +158 -0
- package/dist/cli/commands/refuse-cli-command.js +79 -0
- package/dist/cli/commands/report-arguments.js +62 -0
- package/dist/cli/commands/report-cli-command.js +36 -0
- package/dist/cli/commands/report-usage.js +41 -0
- package/dist/cli/commands/sessions-cli-command.js +184 -0
- package/dist/cli/commands/start-cli-command.js +83 -0
- package/dist/cli/commands/watch-cli-command.js +142 -0
- package/dist/cli/exit-codes.js +13 -0
- package/dist/cli/project-switches.js +46 -0
- package/dist/cli.js +80 -0
- package/dist/composition-root.js +411 -0
- package/dist/core/access/command-line.js +454 -0
- package/dist/core/access/listing.js +58 -0
- package/dist/core/access/path-shape.js +59 -0
- package/dist/core/access/path-tokens.js +37 -0
- package/dist/core/access/protected-access.js +310 -0
- package/dist/core/access/protected-values.js +102 -0
- package/dist/core/access/recorded-effect.js +67 -0
- package/dist/core/access/returns.js +173 -0
- package/dist/core/access/search-output.js +34 -0
- package/dist/core/access/search-reach.js +268 -0
- package/dist/core/access/uses.js +143 -0
- package/dist/core/access/words-before.js +52 -0
- package/dist/core/agent.js +1 -0
- package/dist/core/capability.js +11 -0
- package/dist/core/combined-project-catalogue.js +36 -0
- package/dist/core/combined-session-catalogue.js +25 -0
- package/dist/core/completeness.js +10 -0
- package/dist/core/context.js +1 -0
- package/dist/core/correlation/correlate.js +329 -0
- package/dist/core/delegation.js +1 -0
- package/dist/core/detector/prompt-signals.js +78 -0
- package/dist/core/entry-point.js +1 -0
- package/dist/core/event.js +1 -0
- package/dist/core/evidence.js +9 -0
- package/dist/core/late-message.js +32 -0
- package/dist/core/message.js +1 -0
- package/dist/core/nearest-project.js +28 -0
- package/dist/core/policy/default-policy.js +32 -0
- package/dist/core/policy/glob.js +56 -0
- package/dist/core/policy/parse-policy.js +70 -0
- package/dist/core/policy/policy.js +20 -0
- package/dist/core/policy/resolve-policy.js +16 -0
- package/dist/core/project-catalogue.js +1 -0
- package/dist/core/project-root.js +133 -0
- package/dist/core/provider-titles.js +10 -0
- package/dist/core/redaction/entropy.js +46 -0
- package/dist/core/redaction/redacted.js +4 -0
- package/dist/core/redaction/redactor.js +339 -0
- package/dist/core/redaction/secret-patterns.js +22 -0
- package/dist/core/redaction/value-shapes.js +81 -0
- package/dist/core/redaction/value-trace.js +110 -0
- package/dist/core/review.js +1 -0
- package/dist/core/session-catalogue.js +19 -0
- package/dist/core/session-filter.js +42 -0
- package/dist/core/session-format.js +27 -0
- package/dist/core/session-model.js +1 -0
- package/dist/core/session-reader.js +22 -0
- package/dist/core/session-records.js +1 -0
- package/dist/core/session-source.js +1 -0
- package/dist/core/session-titles.js +21 -0
- package/dist/core/turn.js +1 -0
- package/dist/doctor/codex-doctor.js +14 -0
- package/dist/doctor/doctor-use-case.js +1 -0
- package/dist/doctor/format-selecting-doctor.js +28 -0
- package/dist/doctor/render/attention/attention-rule.js +1 -0
- package/dist/doctor/render/attention/doctor-attention-rules.js +28 -0
- package/dist/doctor/render/attention/rules/damaged-meta-files-rule.js +8 -0
- package/dist/doctor/render/attention/rules/damaged-transcripts-rule.js +9 -0
- package/dist/doctor/render/attention/rules/incomplete-subagent-pairs-rule.js +6 -0
- package/dist/doctor/render/attention/rules/missing-main-transcript-rule.js +5 -0
- package/dist/doctor/render/attention/rules/missing-spilled-results-rule.js +6 -0
- package/dist/doctor/render/attention/rules/multiple-working-directories-rule.js +15 -0
- package/dist/doctor/render/attention/rules/unknown-denial-kinds-rule.js +5 -0
- package/dist/doctor/render/attention/rules/unknown-line-types-rule.js +6 -0
- package/dist/doctor/render/attention/rules/unrecognised-entries-rule.js +6 -0
- package/dist/doctor/render/attention/rules/unusable-directories-rule.js +12 -0
- package/dist/doctor/render/attention/transcript-scopes.js +6 -0
- package/dist/doctor/render/codex-text-doctor-renderer.js +97 -0
- package/dist/doctor/render/doctor-renderers.js +1 -0
- package/dist/doctor/render/json-doctor-renderer.js +7 -0
- package/dist/doctor/render/output-format.js +1 -0
- package/dist/doctor/render/text-doctor-renderer.js +124 -0
- package/dist/doctor/session-doctor.js +16 -0
- package/dist/infrastructure/clack-asker.js +24 -0
- package/dist/infrastructure/clack-chooser.js +40 -0
- package/dist/infrastructure/clack-multi-chooser.js +31 -0
- package/dist/infrastructure/file-alert-store.js +120 -0
- package/dist/infrastructure/file-checked-store.js +55 -0
- package/dist/infrastructure/file-mark-store.js +67 -0
- package/dist/infrastructure/file-onboarding-store.js +93 -0
- package/dist/infrastructure/folder-window.js +26 -0
- package/dist/infrastructure/node-agentwhy-invocation.js +99 -0
- package/dist/infrastructure/node-browser.js +40 -0
- package/dist/infrastructure/node-file-system.js +111 -0
- package/dist/infrastructure/node-local-server.js +115 -0
- package/dist/infrastructure/node-text-input.js +26 -0
- package/dist/infrastructure/os-notifier.js +21 -0
- package/dist/infrastructure/osascript-folder-chooser.js +53 -0
- package/dist/infrastructure/powershell-folder-chooser.js +78 -0
- package/dist/infrastructure/real-directory.js +18 -0
- package/dist/infrastructure/stream-printer.js +11 -0
- package/dist/infrastructure/terminal-banner.js +19 -0
- package/dist/ports/agentwhy-invocation.js +1 -0
- package/dist/ports/alert-store.js +1 -0
- package/dist/ports/asker.js +1 -0
- package/dist/ports/browser.js +1 -0
- package/dist/ports/checked-store.js +1 -0
- package/dist/ports/chooser.js +1 -0
- package/dist/ports/directory-reader.js +1 -0
- package/dist/ports/file-access-error.js +11 -0
- package/dist/ports/file-reader.js +1 -0
- package/dist/ports/file-tail-reader.js +1 -0
- package/dist/ports/file-writer.js +1 -0
- package/dist/ports/folder-chooser.js +1 -0
- package/dist/ports/local-server.js +1 -0
- package/dist/ports/mark-store.js +10 -0
- package/dist/ports/multi-chooser.js +1 -0
- package/dist/ports/notifier.js +1 -0
- package/dist/ports/onboarding-store.js +1 -0
- package/dist/ports/printer.js +1 -0
- package/dist/ports/text-input.js +1 -0
- package/dist/refuse/command-reach.js +135 -0
- package/dist/refuse/command-refusal.js +88 -0
- package/dist/refuse/render/codex-stop-words.js +21 -0
- package/dist/refuse/render/refusal-words.js +34 -0
- package/dist/report/build-report.js +1037 -0
- package/dist/report/check/actions-digest.js +73 -0
- package/dist/report/check/check-lines.js +83 -0
- package/dist/report/check/mark-request.js +90 -0
- package/dist/report/check/marks.js +84 -0
- package/dist/report/check/render/text-digest-renderer.js +332 -0
- package/dist/report/check/session-actions.js +90 -0
- package/dist/report/check/session-check.js +91 -0
- package/dist/report/choose-policy.js +61 -0
- package/dist/report/flow-reads.js +18 -0
- package/dist/report/private-files/tell-lists.js +84 -0
- package/dist/report/project-rules.js +33 -0
- package/dist/report/render/home-relative.js +18 -0
- package/dist/report/render/html-head.js +26 -0
- package/dist/report/render/html-report-components.js +48 -0
- package/dist/report/render/html-report-styles.js +500 -0
- package/dist/report/render/html-sidebar.js +42 -0
- package/dist/report/render/path-tail.js +14 -0
- package/dist/report/render/report-copy.js +1177 -0
- package/dist/report/render/report-page/advanced-view.js +167 -0
- package/dist/report/render/report-page/file-story.js +114 -0
- package/dist/report/render/report-page/files-view.js +381 -0
- package/dist/report/render/report-page/files.js +77 -0
- package/dist/report/render/report-page/fix-wizard-script.js +269 -0
- package/dist/report/render/report-page/fix-wizard.js +310 -0
- package/dist/report/render/report-page/helpers-view.js +383 -0
- package/dist/report/render/report-page/helpers.js +51 -0
- package/dist/report/render/report-page/item-names.js +63 -0
- package/dist/report/render/report-page/protect-patterns.js +13 -0
- package/dist/report/render/report-page/providers.js +208 -0
- package/dist/report/render/report-page/record-view.js +367 -0
- package/dist/report/render/report-page/report-page-renderer.js +129 -0
- package/dist/report/render/report-page/report-views.js +31 -0
- package/dist/report/render/report-page/story-window.js +356 -0
- package/dist/report/render/report-page/times.js +25 -0
- package/dist/report/render/report-page/to-do-view.js +299 -0
- package/dist/report/render/report-page/to-do.js +152 -0
- package/dist/report/render/report-page.js +1 -0
- package/dist/report/render/session-view.js +250 -0
- package/dist/report/render/text-report-renderer.js +981 -0
- package/dist/report/render/ui/add-file-popup.js +122 -0
- package/dist/report/render/ui/app-sidebar.js +78 -0
- package/dist/report/render/ui/ask-panel.js +80 -0
- package/dist/report/render/ui/avatar.js +19 -0
- package/dist/report/render/ui/backdrop.js +29 -0
- package/dist/report/render/ui/brand-mark.js +4 -0
- package/dist/report/render/ui/button.js +67 -0
- package/dist/report/render/ui/callout.js +20 -0
- package/dist/report/render/ui/chat-example.js +17 -0
- package/dist/report/render/ui/checklist.js +50 -0
- package/dist/report/render/ui/confirm-dialog.js +34 -0
- package/dist/report/render/ui/data-table.js +49 -0
- package/dist/report/render/ui/drawer.js +25 -0
- package/dist/report/render/ui/file-chip.js +37 -0
- package/dist/report/render/ui/fold-line.js +22 -0
- package/dist/report/render/ui/guide-card.js +25 -0
- package/dist/report/render/ui/hero.js +37 -0
- package/dist/report/render/ui/labelled-select.js +10 -0
- package/dist/report/render/ui/live-script.js +222 -0
- package/dist/report/render/ui/local-date.js +58 -0
- package/dist/report/render/ui/mode-icon.js +6 -0
- package/dist/report/render/ui/page-shell.js +101 -0
- package/dist/report/render/ui/pill-tabs.js +47 -0
- package/dist/report/render/ui/popup.js +77 -0
- package/dist/report/render/ui/progress.js +35 -0
- package/dist/report/render/ui/project-list.js +284 -0
- package/dist/report/render/ui/scope-choice.js +19 -0
- package/dist/report/render/ui/stats.js +21 -0
- package/dist/report/render/ui/status-icon.js +30 -0
- package/dist/report/render/ui/status-look.js +21 -0
- package/dist/report/render/ui/switch.js +11 -0
- package/dist/report/render/ui/tag.js +19 -0
- package/dist/report/render/ui/task-list.js +56 -0
- package/dist/report/render/ui/tokens.js +46 -0
- package/dist/report/render/ui/update-notice.js +146 -0
- package/dist/report/render/ui/words/app-words.js +163 -0
- package/dist/report/render/ui/words/conversations-words.js +457 -0
- package/dist/report/render/ui/words/month-words.js +59 -0
- package/dist/report/render/ui/words/onboarding-words.js +446 -0
- package/dist/report/render/ui/words/projects-words.js +217 -0
- package/dist/report/render/ui/words/report-words.js +2099 -0
- package/dist/report/render/ui/words/settings-words.js +611 -0
- package/dist/report/render/ui/words/to-fix-words.js +287 -0
- package/dist/report/report-model.js +2 -0
- package/dist/report/report-use-case.js +1 -0
- package/dist/report/rule-names.js +20 -0
- package/dist/report/session-report.js +163 -0
- package/dist/report/start/app-nav.js +37 -0
- package/dist/report/start/conversations/calendar-view.js +104 -0
- package/dist/report/start/conversations/conversation-columns.js +187 -0
- package/dist/report/start/conversations/conversations-renderer.js +54 -0
- package/dist/report/start/conversations/empty-week.js +120 -0
- package/dist/report/start/conversations/files-window.js +166 -0
- package/dist/report/start/conversations/period-section.js +280 -0
- package/dist/report/start/conversations/periods-script.js +440 -0
- package/dist/report/start/conversations/periods.js +110 -0
- package/dist/report/start/conversations/week-view.js +30 -0
- package/dist/report/start/conversations/weeks.js +17 -0
- package/dist/report/start/month/month-renderer.js +50 -0
- package/dist/report/start/month/month-view.js +135 -0
- package/dist/report/start/month/months.js +17 -0
- package/dist/report/start/onboarding/done.js +171 -0
- package/dist/report/start/onboarding/finish-onboarding.js +93 -0
- package/dist/report/start/onboarding/intro.js +100 -0
- package/dist/report/start/onboarding/onboarding-changes.js +40 -0
- package/dist/report/start/onboarding/onboarding-renderer.js +195 -0
- package/dist/report/start/onboarding/onboarding-script.js +400 -0
- package/dist/report/start/onboarding/onboarding-view.js +98 -0
- package/dist/report/start/onboarding/project-step.js +210 -0
- package/dist/report/start/onboarding/steps.js +239 -0
- package/dist/report/start/onboarding/welcome.js +66 -0
- package/dist/report/start/page-notice.js +10 -0
- package/dist/report/start/projects/index-projects.js +43 -0
- package/dist/report/start/projects/moved-page.js +82 -0
- package/dist/report/start/projects/project-switch.js +138 -0
- package/dist/report/start/projects/projects-window.js +67 -0
- package/dist/report/start/projects/temporary-space.js +18 -0
- package/dist/report/start/render/air-datepicker-vendor.js +27 -0
- package/dist/report/start/render/session-status.js +41 -0
- package/dist/report/start/render/start-words.js +84 -0
- package/dist/report/start/repository.js +28 -0
- package/dist/report/start/serve/index-handler.js +372 -0
- package/dist/report/start/serve/onboarding-request.js +50 -0
- package/dist/report/start/serve/settings-request.js +1 -0
- package/dist/report/start/serve/settings-setup.js +193 -0
- package/dist/report/start/session-index.js +1 -0
- package/dist/report/start/session-start.js +974 -0
- package/dist/report/start/settings/alerts-tab.js +104 -0
- package/dist/report/start/settings/files-tab.js +169 -0
- package/dist/report/start/settings/general-tab.js +71 -0
- package/dist/report/start/settings/settings-renderer.js +254 -0
- package/dist/report/start/settings/settings-script.js +161 -0
- package/dist/report/start/settings/settings-view.js +240 -0
- package/dist/report/start/settings/settings-windows.js +334 -0
- package/dist/report/start/settings-files.js +43 -0
- package/dist/report/start/to-fix/done-list.js +45 -0
- package/dist/report/start/to-fix/file-window.js +110 -0
- package/dist/report/start/to-fix/to-fix-list.js +70 -0
- package/dist/report/start/to-fix/to-fix-renderer.js +237 -0
- package/dist/report/start/to-fix/to-fix-script.js +94 -0
- package/dist/report/start/to-fix/to-fix-view.js +124 -0
- package/dist/report/watch/agent-alert.js +72 -0
- package/dist/report/watch/notice-choices.js +35 -0
- package/dist/report/watch/notice-settings.js +65 -0
- package/dist/report/watch/preferences.js +100 -0
- package/dist/report/watch/render/instruction-words.js +54 -0
- package/dist/report/watch/render/notice-words.js +182 -0
- package/dist/report/watch/subagent-watch.js +345 -0
- package/dist/report/watch/watch-notice.js +1 -0
- package/dist/setup/behind.js +18 -0
- package/dist/setup/codex-mirror.js +171 -0
- package/dist/setup/not-a-project.js +19 -0
- package/dist/setup/project-setup.js +644 -0
- package/dist/setup/protected-patterns.js +30 -0
- package/dist/shared/colour.js +23 -0
- package/dist/shared/compare.js +4 -0
- package/dist/shared/content-version.js +13 -0
- package/dist/shared/counter.js +11 -0
- package/dist/shared/file-stamp.js +4 -0
- package/dist/shared/json.js +13 -0
- package/dist/shared/label.js +13 -0
- package/dist/shared/package-name.js +6 -0
- package/dist/shared/plain-invocation.js +44 -0
- package/dist/shared/plain-version.js +21 -0
- package/dist/shared/printable.js +25 -0
- package/dist/shared/renderer.js +1 -0
- package/dist/shared/sentence.js +20 -0
- package/dist/shared/terminal-logo.js +41 -0
- package/dist/shared/text-table.js +15 -0
- package/dist/shared/wrap.js +29 -0
- package/package.json +70 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { homedir, tmpdir } from 'node:os';
|
|
3
|
+
import { EXIT_CODE, HOOK_BLOCK_EXIT_CODE } from './cli/exit-codes.js';
|
|
4
|
+
import { runSwitching } from './cli/project-switches.js';
|
|
5
|
+
import { createCommandRouter, processServer } from './composition-root.js';
|
|
6
|
+
import { colourWanted } from './shared/colour.js';
|
|
7
|
+
// The shell: the only module that touches `process`.
|
|
8
|
+
async function main(argv) {
|
|
9
|
+
// One folder's environment: the one `agentwhy` was typed in, or one a page switched to (which-project V14), with the
|
|
10
|
+
// seams that let its run start the next.
|
|
11
|
+
const environmentAt = (workingDirectory, seams) => ({
|
|
12
|
+
workingDirectory,
|
|
13
|
+
...seams,
|
|
14
|
+
home: homedir(),
|
|
15
|
+
platform: process.platform,
|
|
16
|
+
temporaryDirectory: tmpdir(),
|
|
17
|
+
// Who this process is, for the one store that keeps a file in the shared temporary directory and has to know
|
|
18
|
+
// whether the directory it found there is this person's. Undefined on a platform with no such notion.
|
|
19
|
+
user: process.getuid?.(),
|
|
20
|
+
// A command that behaves differently when it is being watched is not scriptable, so this is asked once,
|
|
21
|
+
// here, and every command is told rather than looking for itself.
|
|
22
|
+
interactive: process.stdin.isTTY === true && process.stdout.isTTY === true,
|
|
23
|
+
// Asked apart from `interactive`: a hook's stdout is never a terminal, but its stdin is a pipe either way.
|
|
24
|
+
inputIsTerminal: process.stdin.isTTY === true,
|
|
25
|
+
// Decided here and once, like `interactive`: a renderer that looked at a stream would colour a piped report.
|
|
26
|
+
colour: colourWanted(process.stdout.isTTY === true, process.env.NO_COLOR),
|
|
27
|
+
// Whether anyone is looking at the output. The wordmark is drawn for a person and not for a pipe, and it is
|
|
28
|
+
// asked apart from `colour`, which NO_COLOR turns off without making the terminal any less of a terminal.
|
|
29
|
+
terminal: process.stdout.isTTY === true,
|
|
30
|
+
// How wide the report may be drawn. Undefined when stdout is not a terminal: a piped report keeps one width,
|
|
31
|
+
// so what a script reads does not depend on the window someone happened to run it in.
|
|
32
|
+
columns: process.stdout.isTTY === true ? process.stdout.columns : undefined,
|
|
33
|
+
input: process.stdin,
|
|
34
|
+
output: process.stdout,
|
|
35
|
+
// Read once per run: every range and every age on a page is measured from the moment its command began - for a run
|
|
36
|
+
// a page switched to, the moment of the switch.
|
|
37
|
+
now: Date.now(),
|
|
38
|
+
// Which way into Claude Code ran this, when a hook did: `cli` and `claude-vscode` have a person reading, and
|
|
39
|
+
// `sdk-cli` is `claude -p` (`the-agent-tells-you.md` B9e2). The hook input says nothing about it; this does.
|
|
40
|
+
entryPoint: process.env.CLAUDE_CODE_ENTRYPOINT,
|
|
41
|
+
// The system's language, in the order POSIX reads it, for a line nobody chose a language for
|
|
42
|
+
// (`the-agent-tells-you.md` R29). An empty variable says nothing, so it is passed over like a missing one.
|
|
43
|
+
locale: process.env.LC_ALL || process.env.LC_MESSAGES || process.env.LANG || undefined,
|
|
44
|
+
// The project a hook runs for, the variable its own `--settings "$CLAUDE_PROJECT_DIR/…"` is expanded with: whose
|
|
45
|
+
// settings say how the hook runs agentwhy, and so how the agent is asked to (`the-agent-tells-you.md` R18).
|
|
46
|
+
projectDirectory: process.env.CLAUDE_PROJECT_DIR || undefined,
|
|
47
|
+
// How this agentwhy runs, which decides the command a hook written now runs (`a-hook-runs-what-you-ran.md` J2):
|
|
48
|
+
// the script as it was started, and the `PATH` a hook's shell would look it up on.
|
|
49
|
+
script: process.argv[1],
|
|
50
|
+
path: process.env.PATH,
|
|
51
|
+
});
|
|
52
|
+
// which-project V14, amended: one page server for the process, so a switched-from project's pages still reach it.
|
|
53
|
+
const server = processServer();
|
|
54
|
+
const result = await runSwitching((workingDirectory, args, seams) => createCommandRouter({ ...environmentAt(workingDirectory, seams), server }).route(args), process.cwd(), argv, write);
|
|
55
|
+
return write(result);
|
|
56
|
+
}
|
|
57
|
+
/** A result, written where it belongs: the output to stdout, a refusal to stderr. The exit code it carries is returned. */
|
|
58
|
+
function write(result) {
|
|
59
|
+
switch (result.kind) {
|
|
60
|
+
case 'help':
|
|
61
|
+
process.stdout.write(result.usage);
|
|
62
|
+
return EXIT_CODE.ok;
|
|
63
|
+
case 'usage-error':
|
|
64
|
+
process.stderr.write(`agentwhy: ${result.message}\n\n${result.usage}`);
|
|
65
|
+
return EXIT_CODE.usage;
|
|
66
|
+
case 'completed':
|
|
67
|
+
process.stdout.write(result.output);
|
|
68
|
+
return result.exitCode;
|
|
69
|
+
case 'hook-block':
|
|
70
|
+
process.stderr.write(result.reason);
|
|
71
|
+
return HOOK_BLOCK_EXIT_CODE;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
process.exitCode = await main(process.argv.slice(2));
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
process.stderr.write(`agentwhy: unexpected error: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
79
|
+
process.exitCode = EXIT_CODE.unexpected;
|
|
80
|
+
}
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A port for a place where nobody can be asked. The served Settings view runs setup with its own confirm step as
|
|
3
|
+
* the consent (R58, `interactive: false`), so a question here would be a question with no one at the other end:
|
|
4
|
+
* it is refused loudly rather than answered with a guess.
|
|
5
|
+
*/
|
|
6
|
+
function unaskable(what) {
|
|
7
|
+
const refuse = () => {
|
|
8
|
+
throw new Error(`agentwhy tried to ask for ${what} where nobody can be asked.`);
|
|
9
|
+
};
|
|
10
|
+
return { choose: refuse, chooseMany: refuse, ask: refuse };
|
|
11
|
+
}
|
|
12
|
+
import { randomUUID } from 'node:crypto';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
import { TellLists, tellListPaths } from './report/private-files/tell-lists.js';
|
|
15
|
+
import { projectDirectoryName } from './adapter/claude-code/contract/projects.js';
|
|
16
|
+
import { ClaudeCodeSessionCatalogue } from './adapter/claude-code/discovery/claude-code-session-catalogue.js';
|
|
17
|
+
import { ClaudeCodeSessionDiscovery } from './adapter/claude-code/discovery/claude-code-session-discovery.js';
|
|
18
|
+
import { ClaudeCodeSessionTitles } from './adapter/claude-code/discovery/claude-code-session-titles.js';
|
|
19
|
+
import { ClaudeCodeProjectCatalogue } from './adapter/claude-code/discovery/claude-code-project-catalogue.js';
|
|
20
|
+
import { ClaudeCodeSessionSource } from './adapter/claude-code/events/claude-code-session-source.js';
|
|
21
|
+
import { ClaudeCodeProbe } from './adapter/claude-code/probe/claude-code-probe.js';
|
|
22
|
+
import { recogniseClaudeCode } from './adapter/claude-code/discovery/claude-code-recognition.js';
|
|
23
|
+
import { recogniseCodex } from './adapter/codex/discovery/codex-recognition.js';
|
|
24
|
+
import { CodexSessionDiscovery } from './adapter/codex/discovery/codex-session-discovery.js';
|
|
25
|
+
import { CodexSessionIndex } from './adapter/codex/discovery/codex-session-index.js';
|
|
26
|
+
import { CodexSessionCatalogue } from './adapter/codex/discovery/codex-session-catalogue.js';
|
|
27
|
+
import { CodexSessionTitles } from './adapter/codex/discovery/codex-session-titles.js';
|
|
28
|
+
import { CodexProjectCatalogue } from './adapter/codex/discovery/codex-project-catalogue.js';
|
|
29
|
+
import { SESSIONS_ROOT as CODEX_SESSIONS_ROOT, THREAD_NAMES } from './adapter/codex/contract/session.js';
|
|
30
|
+
import { CodexSessionSource } from './adapter/codex/events/codex-session-source.js';
|
|
31
|
+
import { CombinedProjectCatalogue } from './core/combined-project-catalogue.js';
|
|
32
|
+
import { CombinedSessionCatalogue } from './core/combined-session-catalogue.js';
|
|
33
|
+
import { ProviderTitles } from './core/provider-titles.js';
|
|
34
|
+
import { FormatSelectingReader } from './core/session-reader.js';
|
|
35
|
+
import { CodexProbe } from './adapter/codex/probe/codex-probe.js';
|
|
36
|
+
import { CommandRouter } from './cli/command-router.js';
|
|
37
|
+
import { CheckCliCommand } from './cli/commands/check-cli-command.js';
|
|
38
|
+
import { InitCliCommand } from './cli/commands/init-cli-command.js';
|
|
39
|
+
import { RefuseCliCommand } from './cli/commands/refuse-cli-command.js';
|
|
40
|
+
import { CodexStopCliCommand } from './cli/commands/codex-stop-cli-command.js';
|
|
41
|
+
import { CodexTurnRefusals } from './adapter/codex/hooks/stop-refusals.js';
|
|
42
|
+
import { DoctorCliCommand } from './cli/commands/doctor-cli-command.js';
|
|
43
|
+
import { ReportCliCommand } from './cli/commands/report-cli-command.js';
|
|
44
|
+
import { SessionsCliCommand } from './cli/commands/sessions-cli-command.js';
|
|
45
|
+
import { MenuCliCommand } from './cli/commands/menu-cli-command.js';
|
|
46
|
+
import { StartCliCommand } from './cli/commands/start-cli-command.js';
|
|
47
|
+
import { NotifyCliCommand } from './cli/commands/notify-cli-command.js';
|
|
48
|
+
import { WatchCliCommand } from './cli/commands/watch-cli-command.js';
|
|
49
|
+
import { widthFor } from './cli/commands/report-usage.js';
|
|
50
|
+
import { Redactor } from './core/redaction/redactor.js';
|
|
51
|
+
import { SessionFormats } from './core/session-format.js';
|
|
52
|
+
import { SessionReport } from './report/session-report.js';
|
|
53
|
+
import { TextDigestRenderer } from './report/check/render/text-digest-renderer.js';
|
|
54
|
+
import { SessionCheck } from './report/check/session-check.js';
|
|
55
|
+
import { CommandRefusal } from './refuse/command-refusal.js';
|
|
56
|
+
import { CodexMirror } from './setup/codex-mirror.js';
|
|
57
|
+
import { ProjectSetup } from './setup/project-setup.js';
|
|
58
|
+
import { ReportPageRenderer } from './report/render/report-page/report-page-renderer.js';
|
|
59
|
+
import { ConversationsRenderer } from './report/start/conversations/conversations-renderer.js';
|
|
60
|
+
import { SettingsRenderer } from './report/start/settings/settings-renderer.js';
|
|
61
|
+
import { MonthRenderer } from './report/start/month/month-renderer.js';
|
|
62
|
+
import { ToFixRenderer } from './report/start/to-fix/to-fix-renderer.js';
|
|
63
|
+
import { SessionStart } from './report/start/session-start.js';
|
|
64
|
+
import { NoticeWordsRenderer } from './report/watch/render/notice-words.js';
|
|
65
|
+
import { NoticeSettings } from './report/watch/notice-settings.js';
|
|
66
|
+
import { SubagentWatch } from './report/watch/subagent-watch.js';
|
|
67
|
+
import { TextReportRenderer } from './report/render/text-report-renderer.js';
|
|
68
|
+
import { createDoctorAttentionRules } from './doctor/render/attention/doctor-attention-rules.js';
|
|
69
|
+
import { JsonDoctorRenderer } from './doctor/render/json-doctor-renderer.js';
|
|
70
|
+
import { TextDoctorRenderer } from './doctor/render/text-doctor-renderer.js';
|
|
71
|
+
import { SessionDoctor } from './doctor/session-doctor.js';
|
|
72
|
+
import { CodexDoctor } from './doctor/codex-doctor.js';
|
|
73
|
+
import { FormatSelectingDoctor } from './doctor/format-selecting-doctor.js';
|
|
74
|
+
import { CodexTextDoctorRenderer } from './doctor/render/codex-text-doctor-renderer.js';
|
|
75
|
+
import { NodeBrowser } from './infrastructure/node-browser.js';
|
|
76
|
+
import { OsascriptFolderChooser } from './infrastructure/osascript-folder-chooser.js';
|
|
77
|
+
import { PowershellFolderChooser } from './infrastructure/powershell-folder-chooser.js';
|
|
78
|
+
import { ClackAsker } from './infrastructure/clack-asker.js';
|
|
79
|
+
import { ClackChooser } from './infrastructure/clack-chooser.js';
|
|
80
|
+
import { ClackMultiChooser } from './infrastructure/clack-multi-chooser.js';
|
|
81
|
+
import { FileMarkStore } from './infrastructure/file-mark-store.js';
|
|
82
|
+
import { FileCheckedStore } from './infrastructure/file-checked-store.js';
|
|
83
|
+
import { FileOnboardingStore } from './infrastructure/file-onboarding-store.js';
|
|
84
|
+
import { OnboardingRenderer } from './report/start/onboarding/onboarding-renderer.js';
|
|
85
|
+
import { NodeFileSystem } from './infrastructure/node-file-system.js';
|
|
86
|
+
import { realDirectory } from './infrastructure/real-directory.js';
|
|
87
|
+
import { NodeAgentwhyInvocation } from './infrastructure/node-agentwhy-invocation.js';
|
|
88
|
+
import { NodeLocalServer } from './infrastructure/node-local-server.js';
|
|
89
|
+
import { NodeTextInput } from './infrastructure/node-text-input.js';
|
|
90
|
+
import { StreamPrinter } from './infrastructure/stream-printer.js';
|
|
91
|
+
import { TerminalBanner } from './infrastructure/terminal-banner.js';
|
|
92
|
+
import { FileAlertStore } from './infrastructure/file-alert-store.js';
|
|
93
|
+
import { OsNotifier } from './infrastructure/os-notifier.js';
|
|
94
|
+
import { TAGLINE, terminalLogo } from './shared/terminal-logo.js';
|
|
95
|
+
/**
|
|
96
|
+
* Where a person's answers about being told are kept (`the-agent-tells-you.md` R22): one file, beside the marks,
|
|
97
|
+
* under the directory this tool already owns in their home - outside every project, and so outside every repository.
|
|
98
|
+
*/
|
|
99
|
+
export function preferencesPath(environment) {
|
|
100
|
+
return join(environment.home, '.agentwhy', 'notices.json');
|
|
101
|
+
}
|
|
102
|
+
/** Where the pages `start` writes lead to one another. */
|
|
103
|
+
const APP_LINKS = { conversations: 'index.html', toFix: 'to-fix.html', month: 'month.html', settings: 'settings.html', onboarding: 'onboarding.html' };
|
|
104
|
+
/**
|
|
105
|
+
* The page server for a whole process (`.ai/specs/2026-09-27-which-project.md` V14, amended 2026-09-28): every project a
|
|
106
|
+
* page switches to is served at the same address, so the pages of the one before still reach it.
|
|
107
|
+
*/
|
|
108
|
+
export function processServer() {
|
|
109
|
+
return new NodeLocalServer();
|
|
110
|
+
}
|
|
111
|
+
export function createCommandRouter(environment) {
|
|
112
|
+
const files = new NodeFileSystem();
|
|
113
|
+
// which-project V6: the home directory as a working directory is given, every link followed - read only to tell a
|
|
114
|
+
// run started there. Every other use keeps `home` as the shell gave it.
|
|
115
|
+
const realHome = realDirectory(environment.home);
|
|
116
|
+
// J1-J3: how this agentwhy runs, for every hook written in this run and for the command `watch` offers.
|
|
117
|
+
const invocation = new NodeAgentwhyInvocation({ script: environment.script, path: environment.path, platform: environment.platform });
|
|
118
|
+
// `check` lists Claude Code's sessions alone: the Codex specification covers `doctor`, `report` and the pages `start`
|
|
119
|
+
// serves, and nothing else (`.ai/plans/2026-09-29-what-codex-wrote.md` step 8's audit). `watch` and every hook read
|
|
120
|
+
// Claude Code alone too, by their own source.
|
|
121
|
+
const claudeCatalogue = new ClaudeCodeSessionCatalogue(files, environment.home);
|
|
122
|
+
// XD7: the one registry that tells formats apart by content - Codex's strict first-line rule first - read by `doctor`,
|
|
123
|
+
// `report`, `start` and `sessions`. One listing of Codex's root serves the catalogue and the reports it lists.
|
|
124
|
+
const codexDiscovery = new CodexSessionDiscovery({ directories: files, files });
|
|
125
|
+
const codexIndex = new CodexSessionIndex(codexDiscovery);
|
|
126
|
+
const codexRoot = join(environment.home, ...CODEX_SESSIONS_ROOT);
|
|
127
|
+
const codexCatalogue = new CodexSessionCatalogue({ index: codexIndex, directories: files, sessionsRoot: codexRoot });
|
|
128
|
+
// XD5: one list of a project's conversations for both AIs, each row naming its AI.
|
|
129
|
+
const catalogue = new CombinedSessionCatalogue([claudeCatalogue, codexCatalogue]);
|
|
130
|
+
// codex-blocks-too CK6: a project uses Codex where a Codex conversation is listed for it.
|
|
131
|
+
const codexConversations = async () => (await codexCatalogue.list(environment.workingDirectory)).sessions.length > 0;
|
|
132
|
+
const formats = new SessionFormats([
|
|
133
|
+
{ provider: 'codex', recognise: (input) => recogniseCodex(codexDiscovery, files, input) },
|
|
134
|
+
{ provider: 'claude-code', recognise: (input) => recogniseClaudeCode(files, input) },
|
|
135
|
+
]);
|
|
136
|
+
const doctor = new FormatSelectingDoctor({
|
|
137
|
+
formats,
|
|
138
|
+
doctors: {
|
|
139
|
+
codex: new CodexDoctor({
|
|
140
|
+
probe: new CodexProbe({ discovery: codexDiscovery, directories: files, files }),
|
|
141
|
+
renderers: { text: new CodexTextDoctorRenderer(), json: new JsonDoctorRenderer() },
|
|
142
|
+
}),
|
|
143
|
+
'claude-code': new SessionDoctor({
|
|
144
|
+
discovery: new ClaudeCodeSessionDiscovery(files),
|
|
145
|
+
probe: new ClaudeCodeProbe(files),
|
|
146
|
+
renderers: {
|
|
147
|
+
text: new TextDoctorRenderer(createDoctorAttentionRules()),
|
|
148
|
+
json: new JsonDoctorRenderer(),
|
|
149
|
+
},
|
|
150
|
+
}),
|
|
151
|
+
},
|
|
152
|
+
whenUnavailable: 'claude-code',
|
|
153
|
+
});
|
|
154
|
+
// One opener, so a report and an index are shown the same way.
|
|
155
|
+
const browser = new NodeBrowser(environment.platform);
|
|
156
|
+
// F57: the files a person asked only to be told about, read with the policy by every command that chooses one, so
|
|
157
|
+
// an alert, a report and a refusal never read the same file differently.
|
|
158
|
+
const tell = tellListPaths(environment.home, environment.workingDirectory);
|
|
159
|
+
const tellLists = new TellLists({ files, writer: files, paths: tell });
|
|
160
|
+
const report = new SessionReport({
|
|
161
|
+
reader: new FormatSelectingReader({
|
|
162
|
+
formats,
|
|
163
|
+
sources: {
|
|
164
|
+
codex: new CodexSessionSource({ discovery: codexDiscovery, files, sessionsRoot: codexRoot, index: codexIndex }),
|
|
165
|
+
'claude-code': new ClaudeCodeSessionSource({ discovery: new ClaudeCodeSessionDiscovery(files), files }),
|
|
166
|
+
},
|
|
167
|
+
whenUnavailable: 'claude-code',
|
|
168
|
+
}),
|
|
169
|
+
files,
|
|
170
|
+
tell,
|
|
171
|
+
// A salt per run, so a pseudonym says "the same value" inside one report and nothing at all outside it.
|
|
172
|
+
createRedactor: (projectRoot, share) => new Redactor(randomUUID(), projectRoot, share),
|
|
173
|
+
createRenderer: (options) => new TextReportRenderer(options.width, {
|
|
174
|
+
ascii: options.ascii,
|
|
175
|
+
full: options.full,
|
|
176
|
+
colour: environment.colour && options.colour,
|
|
177
|
+
}),
|
|
178
|
+
htmlRenderer: new ReportPageRenderer(),
|
|
179
|
+
// A record's time on the page is this machine's, as the days on Conversations are (the report page spec M4).
|
|
180
|
+
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
181
|
+
catalogue,
|
|
182
|
+
workingDirectory: environment.workingDirectory,
|
|
183
|
+
browser,
|
|
184
|
+
temporaryDirectory: environment.temporaryDirectory,
|
|
185
|
+
now: environment.now,
|
|
186
|
+
});
|
|
187
|
+
// Its own salt: a pseudonym in a title means "the same value" within one list of sessions and nothing beyond it.
|
|
188
|
+
// One process runs one command, so `start` and `sessions` never share a list; both AIs' titles are one list's.
|
|
189
|
+
// Codex's are the names Codex gave its threads (`THREAD_NAMES`, measured 2026-09-30); a thread it named nothing - a
|
|
190
|
+
// `codex exec` run - keeps the missing-title state rather than a message guessed at.
|
|
191
|
+
const titleRedactor = new Redactor(randomUUID());
|
|
192
|
+
const titles = new ProviderTitles({
|
|
193
|
+
'claude-code': new ClaudeCodeSessionTitles({ transcripts: files, redactor: titleRedactor }),
|
|
194
|
+
codex: new CodexSessionTitles({ files, directories: files, path: join(environment.home, ...THREAD_NAMES.file), redactor: titleRedactor }),
|
|
195
|
+
});
|
|
196
|
+
// which-project V9-V11: the person's projects, for the window the sidebar's card opens. A title from another project
|
|
197
|
+
// passes a redactor of its own, as this project's titles do.
|
|
198
|
+
// A folder only Codex worked in is listed under the id Claude Code would give it, so a folder in both is one project
|
|
199
|
+
// (decided 2026-09-29).
|
|
200
|
+
const projects = new CombinedProjectCatalogue([
|
|
201
|
+
new ClaudeCodeProjectCatalogue({ directories: files, transcripts: files, redactor: new Redactor(randomUUID()), home: environment.home }),
|
|
202
|
+
new CodexProjectCatalogue({ index: codexIndex, directories: files, sessionsRoot: codexRoot, projectId: projectDirectoryName }),
|
|
203
|
+
]);
|
|
204
|
+
// One person's record of what they did about a file, beside nothing else and outside every project
|
|
205
|
+
// (`worth-running-every-day` R33). The directory is named the way Claude Code names the project's sessions.
|
|
206
|
+
const projectRecords = join(environment.home, '.agentwhy', 'projects', projectDirectoryName(environment.workingDirectory));
|
|
207
|
+
const marks = new FileMarkStore(join(projectRecords, 'marks.jsonl'));
|
|
208
|
+
// Beside it, the conversations a person asked to check although they were older than a run (F55).
|
|
209
|
+
const checked = new FileCheckedStore(join(projectRecords, 'checked.jsonl'));
|
|
210
|
+
// Whether this person finished the onboarding, here and anywhere: one file for every project, since the intro plays
|
|
211
|
+
// once per person (`.ai/specs/2026-09-24-onboarding.md` W21, N1, N2). Outside every project, as the marks are.
|
|
212
|
+
const onboarding = new FileOnboardingStore(join(environment.home, '.agentwhy', 'onboarding.jsonl'), projectDirectoryName(environment.workingDirectory));
|
|
213
|
+
// One set of rules for the preferences file, with two ways in: this command, and the page's Notifications panel.
|
|
214
|
+
const notices = new NoticeSettings({
|
|
215
|
+
files,
|
|
216
|
+
writer: files,
|
|
217
|
+
path: preferencesPath(environment),
|
|
218
|
+
workingDirectory: environment.workingDirectory,
|
|
219
|
+
});
|
|
220
|
+
const start = new SessionStart({
|
|
221
|
+
catalogue,
|
|
222
|
+
report,
|
|
223
|
+
files,
|
|
224
|
+
tell,
|
|
225
|
+
tellLists,
|
|
226
|
+
// live-pages L4: a clock that only moves forward, to space out reading a session the agent is still writing.
|
|
227
|
+
elapsed: () => performance.now(),
|
|
228
|
+
policyFiles: files,
|
|
229
|
+
directories: files,
|
|
230
|
+
browser,
|
|
231
|
+
// The Conversations page is the index; To fix, This month and Settings are pages of their own, on the UI kit.
|
|
232
|
+
// The earlier page they were views of is gone (`.ai/plans/2026-09-23-to-fix-redesign.md` step 4).
|
|
233
|
+
renderer: new ConversationsRenderer(APP_LINKS),
|
|
234
|
+
pages: {
|
|
235
|
+
[APP_LINKS.month]: new MonthRenderer(APP_LINKS),
|
|
236
|
+
[APP_LINKS.toFix]: new ToFixRenderer(APP_LINKS),
|
|
237
|
+
[APP_LINKS.settings]: new SettingsRenderer(APP_LINKS),
|
|
238
|
+
},
|
|
239
|
+
// Days and times on the page are this machine's (`for-people-who-build-with-ai.md` O2).
|
|
240
|
+
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
241
|
+
digest: new TextDigestRenderer('counts', { colour: environment.colour }),
|
|
242
|
+
marks,
|
|
243
|
+
checked,
|
|
244
|
+
// The first page a project's first served run opens (W23), and written with every served run (W25).
|
|
245
|
+
onboarding: { page: new OnboardingRenderer(APP_LINKS), file: APP_LINKS.onboarding, store: onboarding },
|
|
246
|
+
titles,
|
|
247
|
+
projects,
|
|
248
|
+
// which-project V14, V15: another project shown in the same tab, by a run the shell starts beside this one.
|
|
249
|
+
...(environment.switchTo === undefined ? {} : { switchTo: environment.switchTo }),
|
|
250
|
+
...(environment.handedOver === undefined ? {} : { handedOver: environment.handedOver }),
|
|
251
|
+
...(environment.arrivedFrom === undefined ? {} : { arrivedFrom: environment.arrivedFrom }),
|
|
252
|
+
...(environment.served === undefined ? {} : { served: environment.served }),
|
|
253
|
+
...(environment.pastRuns === undefined ? {} : { pastRuns: environment.pastRuns }),
|
|
254
|
+
// V12: the computer's own folder window - macOS's, measured (VB1), or Windows', not yet (VB7). Elsewhere none.
|
|
255
|
+
folderChooser: environment.platform === 'win32' ? new PowershellFolderChooser(environment.platform) : new OsascriptFolderChooser(environment.platform),
|
|
256
|
+
// R50-R54: the page `start` opens is served from the loopback address, behind a token only that page is given.
|
|
257
|
+
server: environment.server ?? new NodeLocalServer(),
|
|
258
|
+
// R58: a change made in Settings runs through the same setup a terminal runs. Nothing here can ask a question:
|
|
259
|
+
// the page's own confirm step is the consent, so the choosers are never reached and say so if they ever are.
|
|
260
|
+
// nothing-updates-by-itself U2: the version this run is, beside the hooks' own, for the update notice.
|
|
261
|
+
invocation,
|
|
262
|
+
// codex-blocks-too CK5: every write of Claude Code's `refuse` - a switch, Finish blocking, the onboarding - writes
|
|
263
|
+
// Codex's with it, in a project that uses Codex.
|
|
264
|
+
setup: new CodexMirror({
|
|
265
|
+
setup: new ProjectSetup({
|
|
266
|
+
files,
|
|
267
|
+
chooser: unaskable('a choice'),
|
|
268
|
+
hookChooser: unaskable('a list'),
|
|
269
|
+
asker: unaskable('a question'),
|
|
270
|
+
interactive: false,
|
|
271
|
+
workingDirectory: environment.workingDirectory,
|
|
272
|
+
home: environment.home,
|
|
273
|
+
realHome,
|
|
274
|
+
invocation,
|
|
275
|
+
}),
|
|
276
|
+
files,
|
|
277
|
+
chooser: unaskable('a choice'),
|
|
278
|
+
interactive: false,
|
|
279
|
+
workingDirectory: environment.workingDirectory,
|
|
280
|
+
invocation,
|
|
281
|
+
codexConversations,
|
|
282
|
+
}),
|
|
283
|
+
// R26a: the panel that says what a person is told, writing the one file outside every project.
|
|
284
|
+
notices,
|
|
285
|
+
printer: new StreamPrinter(environment.output),
|
|
286
|
+
// The wordmark above the answer, and colour over it: both decided in the shell, neither read from a stream here.
|
|
287
|
+
terminal: { colour: environment.colour, decorated: environment.terminal },
|
|
288
|
+
token: () => randomUUID(),
|
|
289
|
+
clock: () => Date.now(),
|
|
290
|
+
workingDirectory: environment.workingDirectory,
|
|
291
|
+
home: environment.home,
|
|
292
|
+
realHome,
|
|
293
|
+
temporaryDirectory: environment.temporaryDirectory,
|
|
294
|
+
now: environment.now,
|
|
295
|
+
});
|
|
296
|
+
const check = new SessionCheck({
|
|
297
|
+
catalogue: claudeCatalogue,
|
|
298
|
+
report,
|
|
299
|
+
files,
|
|
300
|
+
tell,
|
|
301
|
+
createRenderer: (options) => new TextDigestRenderer(options.full ? 'full' : 'brief', { colour: environment.colour }),
|
|
302
|
+
marks,
|
|
303
|
+
workingDirectory: environment.workingDirectory,
|
|
304
|
+
now: environment.now,
|
|
305
|
+
});
|
|
306
|
+
const watch = new SubagentWatch({
|
|
307
|
+
source: new ClaudeCodeSessionSource({ discovery: new ClaudeCodeSessionDiscovery(files), files }),
|
|
308
|
+
files,
|
|
309
|
+
tell,
|
|
310
|
+
input: new NodeTextInput(environment.input),
|
|
311
|
+
// Its own salt, as every report has: nothing it redacts means anything outside this one run.
|
|
312
|
+
createRedactor: (projectRoot) => new Redactor(randomUUID(), projectRoot, false),
|
|
313
|
+
renderer: new NoticeWordsRenderer(),
|
|
314
|
+
notifier: new OsNotifier(environment.platform),
|
|
315
|
+
home: environment.home,
|
|
316
|
+
// What one hook run leaves for the next: outside every project, and swept by age (`a-notice-in-the-conversation` R7).
|
|
317
|
+
store: new FileAlertStore(environment.temporaryDirectory, environment.user),
|
|
318
|
+
// What a person chose about being told: their own file, outside every project, read on every run (R22, R25).
|
|
319
|
+
preferencesPath: preferencesPath(environment),
|
|
320
|
+
// R14: the agent is asked to speak only where a person is reading, and the entry point is what says so.
|
|
321
|
+
...(environment.entryPoint === undefined ? {} : { entryPoint: environment.entryPoint }),
|
|
322
|
+
// R29: the language of a line nobody chose one for.
|
|
323
|
+
...(environment.locale === undefined ? {} : { locale: environment.locale }),
|
|
324
|
+
// R18: the agent runs agentwhy the way this project's hook does; J6: else the way this hook was started.
|
|
325
|
+
...(environment.projectDirectory === undefined ? {} : { projectDirectory: environment.projectDirectory }),
|
|
326
|
+
invocation,
|
|
327
|
+
});
|
|
328
|
+
// Drawn above the first question each of these commands asks, and not again: one banner per command.
|
|
329
|
+
const logo = () => new TerminalBanner(terminalLogo([TAGLINE], { colour: environment.colour, ascii: false }));
|
|
330
|
+
const setupBanner = logo();
|
|
331
|
+
// Registration order is the order `--help` lists them in, so the way in comes first.
|
|
332
|
+
const start_ = new StartCliCommand({ start, now: environment.now });
|
|
333
|
+
const check_ = new CheckCliCommand({ check, now: environment.now });
|
|
334
|
+
const setupChooser = new ClackChooser(environment.input, environment.output, setupBanner);
|
|
335
|
+
const init_ = new InitCliCommand(new CodexMirror({
|
|
336
|
+
setup: new ProjectSetup({
|
|
337
|
+
files,
|
|
338
|
+
chooser: setupChooser,
|
|
339
|
+
hookChooser: new ClackMultiChooser(environment.input, environment.output, setupBanner),
|
|
340
|
+
asker: new ClackAsker(environment.input, environment.output, setupBanner),
|
|
341
|
+
interactive: environment.interactive,
|
|
342
|
+
workingDirectory: environment.workingDirectory,
|
|
343
|
+
home: environment.home,
|
|
344
|
+
realHome,
|
|
345
|
+
invocation,
|
|
346
|
+
}),
|
|
347
|
+
files,
|
|
348
|
+
chooser: setupChooser,
|
|
349
|
+
interactive: environment.interactive,
|
|
350
|
+
workingDirectory: environment.workingDirectory,
|
|
351
|
+
invocation,
|
|
352
|
+
codexConversations,
|
|
353
|
+
}));
|
|
354
|
+
// One banner for both ports this command can ask through - the range question, then the list - so it is drawn once.
|
|
355
|
+
const sessionsBanner = logo();
|
|
356
|
+
const sessions_ = new SessionsCliCommand({
|
|
357
|
+
catalogue,
|
|
358
|
+
workingDirectory: environment.workingDirectory,
|
|
359
|
+
chooser: new ClackChooser(environment.input, environment.output, sessionsBanner),
|
|
360
|
+
asker: new ClackAsker(environment.input, environment.output, sessionsBanner),
|
|
361
|
+
titles,
|
|
362
|
+
report,
|
|
363
|
+
width: widthFor(environment.columns),
|
|
364
|
+
interactive: environment.interactive,
|
|
365
|
+
now: environment.now,
|
|
366
|
+
});
|
|
367
|
+
// `agentwhy menu`: the few things to do here, in the order most people want them.
|
|
368
|
+
const menu = new MenuCliCommand({
|
|
369
|
+
chooser: new ClackChooser(environment.input, environment.output, logo()),
|
|
370
|
+
printer: new StreamPrinter(environment.output),
|
|
371
|
+
interactive: environment.interactive,
|
|
372
|
+
// Named by what a person gets, with the command beside it. `start` leads while `check`'s rows are unmeasured
|
|
373
|
+
// (spec §5): a page carries a row that turns out to be a mention far better than a list in a terminal does.
|
|
374
|
+
entries: [
|
|
375
|
+
{ label: 'Open the last 7 days of sessions', detail: 'agentwhy start', command: start_ },
|
|
376
|
+
{ label: 'List what to rotate or check', detail: 'agentwhy check', command: check_ },
|
|
377
|
+
{ label: 'Open one session', detail: 'agentwhy sessions', command: sessions_ },
|
|
378
|
+
// The hint carries the words a person searches by - the list filters on both, and "settings" is what
|
|
379
|
+
// this is called out loud, while `init` is what the command is called.
|
|
380
|
+
{ label: 'Set up protection for this project', detail: "agentwhy init · what agents can do, what's protected", command: init_ },
|
|
381
|
+
],
|
|
382
|
+
});
|
|
383
|
+
// R72-R73: a bare `agentwhy` opens the page, and only where a person is there to see it. With no terminal there is
|
|
384
|
+
// no such command, so the router's usage error stands and nothing is opened or served.
|
|
385
|
+
return new CommandRouter([
|
|
386
|
+
start_,
|
|
387
|
+
menu,
|
|
388
|
+
// Then the command a person runs every day, and the one that sets a project up to be told without asking.
|
|
389
|
+
check_,
|
|
390
|
+
init_,
|
|
391
|
+
sessions_,
|
|
392
|
+
// What a person wants to be told, and where: the file the hook reads, changed from a terminal or from the page.
|
|
393
|
+
new NotifyCliCommand({ settings: notices }),
|
|
394
|
+
new ReportCliCommand(report, environment.columns),
|
|
395
|
+
new DoctorCliCommand(doctor),
|
|
396
|
+
// Last: it is run by a hook, not by a person looking for where to begin.
|
|
397
|
+
new WatchCliCommand({ watch, interactive: environment.inputIsTerminal }),
|
|
398
|
+
new RefuseCliCommand({
|
|
399
|
+
refusal: new CommandRefusal({
|
|
400
|
+
input: new NodeTextInput(environment.input),
|
|
401
|
+
files,
|
|
402
|
+
directories: files,
|
|
403
|
+
workingDirectory: environment.workingDirectory,
|
|
404
|
+
home: environment.home,
|
|
405
|
+
tell,
|
|
406
|
+
}),
|
|
407
|
+
interactive: environment.inputIsTerminal,
|
|
408
|
+
}),
|
|
409
|
+
new CodexStopCliCommand(new CodexTurnRefusals(new NodeTextInput(environment.input), files), environment.inputIsTerminal),
|
|
410
|
+
], environment.interactive ? start_ : undefined);
|
|
411
|
+
}
|