@erclx/aitk 0.8.0
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 +21 -0
- package/README.md +99 -0
- package/claude/.claude-plugin/plugin.json +19 -0
- package/claude/skills/bash-script/SKILL.md +96 -0
- package/claude/skills/bash-script/references/patterns.md +349 -0
- package/claude/skills/ci-workflow/SKILL.md +52 -0
- package/claude/skills/ci-workflow/references/workflows.md +74 -0
- package/claude/skills/claude-address-review/SKILL.md +107 -0
- package/claude/skills/claude-autoship/SKILL.md +137 -0
- package/claude/skills/claude-design-extract/SKILL.md +69 -0
- package/claude/skills/claude-design-propose/SKILL.md +75 -0
- package/claude/skills/claude-diagram/SKILL.md +126 -0
- package/claude/skills/claude-docs/SKILL.md +204 -0
- package/claude/skills/claude-feature/REQUIREMENT.md +35 -0
- package/claude/skills/claude-feature/SKILL.md +148 -0
- package/claude/skills/claude-groundwork/SKILL.md +148 -0
- package/claude/skills/claude-groundwork/references/folder-format.md +107 -0
- package/claude/skills/claude-memory-capture/SKILL.md +80 -0
- package/claude/skills/claude-memory-review/REQUIREMENT.md +37 -0
- package/claude/skills/claude-memory-review/SKILL.md +206 -0
- package/claude/skills/claude-orchestrate/SKILL.md +125 -0
- package/claude/skills/claude-pr-review/SKILL.md +150 -0
- package/claude/skills/claude-review/SKILL.md +136 -0
- package/claude/skills/claude-roadmap/SKILL.md +61 -0
- package/claude/skills/claude-roadmap/references/roadmap.md +52 -0
- package/claude/skills/claude-screencast/SKILL.md +160 -0
- package/claude/skills/claude-seed-sync/SKILL.md +141 -0
- package/claude/skills/claude-slides-draft/SKILL.md +62 -0
- package/claude/skills/claude-standards-audit/REQUIREMENT.md +33 -0
- package/claude/skills/claude-standards-audit/SKILL.md +79 -0
- package/claude/skills/claude-standards-audit/references/branch.md +49 -0
- package/claude/skills/claude-standards-audit/references/pr.md +124 -0
- package/claude/skills/claude-tasks/SKILL.md +123 -0
- package/claude/skills/claude-ui-test/SKILL.md +75 -0
- package/claude/skills/claude-ux-audit/SKILL.md +78 -0
- package/claude/skills/claude-worktree/SKILL.md +79 -0
- package/claude/skills/cli-script/SKILL.md +47 -0
- package/claude/skills/cli-script/references/template.md +43 -0
- package/claude/skills/create-rule/SKILL.md +68 -0
- package/claude/skills/create-skill/REQUIREMENT.md +30 -0
- package/claude/skills/create-skill/SKILL.md +24 -0
- package/claude/skills/create-snippet/SKILL.md +28 -0
- package/claude/skills/create-snippet/references/snippets.md +57 -0
- package/claude/skills/create-standard/SKILL.md +31 -0
- package/claude/skills/create-standard/references/standard.md +52 -0
- package/claude/skills/docs-sync/SKILL.md +87 -0
- package/claude/skills/git-branch/REQUIREMENT.md +38 -0
- package/claude/skills/git-branch/SKILL.md +60 -0
- package/claude/skills/git-branch/references/branch.md +49 -0
- package/claude/skills/git-commit/REQUIREMENT.md +33 -0
- package/claude/skills/git-commit/SKILL.md +51 -0
- package/claude/skills/git-commit/references/commit.md +63 -0
- package/claude/skills/git-followup/REQUIREMENT.md +38 -0
- package/claude/skills/git-followup/SKILL.md +35 -0
- package/claude/skills/git-issue/REQUIREMENT.md +38 -0
- package/claude/skills/git-issue/SKILL.md +69 -0
- package/claude/skills/git-issue/references/issue.md +84 -0
- package/claude/skills/git-pr/REQUIREMENT.md +37 -0
- package/claude/skills/git-pr/SKILL.md +119 -0
- package/claude/skills/git-pr/references/branch.md +49 -0
- package/claude/skills/git-pr/references/pr.md +124 -0
- package/claude/skills/git-ship/REQUIREMENT.md +34 -0
- package/claude/skills/git-ship/SKILL.md +39 -0
- package/claude/skills/git-split/REQUIREMENT.md +38 -0
- package/claude/skills/git-split/SKILL.md +160 -0
- package/claude/skills/git-split/references/branch.md +49 -0
- package/claude/skills/git-split/references/pr.md +124 -0
- package/claude/skills/git-stage/REQUIREMENT.md +36 -0
- package/claude/skills/git-stage/SKILL.md +74 -0
- package/claude/skills/git-stage/references/commit.md +63 -0
- package/claude/skills/git-worktree/REQUIREMENT.md +37 -0
- package/claude/skills/git-worktree/SKILL.md +120 -0
- package/claude/skills/migration-claude-md/SKILL.md +74 -0
- package/claude/skills/migration-context/SKILL.md +93 -0
- package/claude/skills/migration-standards/SKILL.md +75 -0
- package/claude/skills/project-commands/SKILL.md +73 -0
- package/claude/skills/session-resume/SKILL.md +36 -0
- package/claude/skills/setup-gov/SKILL.md +71 -0
- package/claude/skills/setup-indexes/SKILL.md +148 -0
- package/claude/skills/setup-init/SKILL.md +114 -0
- package/claude/skills/setup-plugins/SKILL.md +81 -0
- package/claude/skills/setup-plugins/references/plugin-catalog.md +53 -0
- package/claude/skills/setup-verify/SKILL.md +51 -0
- package/claude/skills/systematic-debugging/SKILL.md +70 -0
- package/claude/skills/toolkit-cli/SKILL.md +38 -0
- package/claude/skills/toolkit-feedback/SKILL.md +80 -0
- package/claude/skills/toolkit-operator/SKILL.md +45 -0
- package/claude/skills/toolkit-triage/SKILL.md +63 -0
- package/claude/skills/youtube-transcripts/SKILL.md +34 -0
- package/docs/agents.md +371 -0
- package/docs/ai-workflow.md +157 -0
- package/docs/index.md +20 -0
- package/docs/operating-model.md +106 -0
- package/docs/target-projects.md +183 -0
- package/docs/visual-design-workflow.md +136 -0
- package/docs/zshrc-aliases.md +65 -0
- package/governance/rules/claude/500-prose.md +12 -0
- package/governance/rules/claude/510-context.md +16 -0
- package/governance/rules/claude/520-wireframes.md +12 -0
- package/governance/rules/claude/530-requirements.md +11 -0
- package/governance/rules/claude/540-architecture.md +11 -0
- package/governance/rules/claude/550-design.md +11 -0
- package/governance/rules/claude/555-tasks.md +12 -0
- package/governance/rules/claude/560-diagrams.md +11 -0
- package/governance/rules/claude/570-skill.md +18 -0
- package/governance/rules/claude/580-readme.md +11 -0
- package/governance/rules/claude/590-rule-authoring.md +12 -0
- package/governance/rules/core/000-constitution.md +30 -0
- package/governance/rules/core/010-testing.md +35 -0
- package/governance/rules/core/020-concurrency.md +22 -0
- package/governance/rules/core/030-error-handling.md +31 -0
- package/governance/rules/core/040-performance.md +20 -0
- package/governance/rules/core/050-logging.md +20 -0
- package/governance/rules/core/060-naming.md +19 -0
- package/governance/rules/core/070-planning.md +13 -0
- package/governance/rules/core/080-config-comments.md +22 -0
- package/governance/rules/framework/200-react.md +51 -0
- package/governance/rules/framework/210-astro.md +41 -0
- package/governance/rules/framework/220-fastapi.md +43 -0
- package/governance/rules/framework/230-nextjs.md +48 -0
- package/governance/rules/framework/250-tailwind.md +32 -0
- package/governance/rules/framework/260-shadcn.md +34 -0
- package/governance/rules/lang/100-typescript.md +40 -0
- package/governance/rules/lang/110-python.md +42 -0
- package/governance/rules/lib/300-testing-ts.md +38 -0
- package/governance/rules/lib/310-zod.md +25 -0
- package/governance/rules/lib/320-tanstack-query.md +32 -0
- package/governance/rules/lib/330-testing-py.md +44 -0
- package/governance/rules/lib/340-pydantic.md +38 -0
- package/governance/rules/lib/350-security-web.md +31 -0
- package/governance/rules/ui/400-ui.md +34 -0
- package/governance/rules/ui/410-a11y.md +44 -0
- package/governance/rules/ui/420-forms.md +34 -0
- package/governance/rules/ui/430-ux-completeness.md +62 -0
- package/governance/stacks/astro.toml +2 -0
- package/governance/stacks/base.toml +2 -0
- package/governance/stacks/node.toml +2 -0
- package/governance/stacks/python-fastapi.toml +2 -0
- package/governance/stacks/python.toml +2 -0
- package/governance/stacks/react.toml +2 -0
- package/package.json +67 -0
- package/scripts/config.sh +11 -0
- package/scripts/core/bootstrap.sh +81 -0
- package/scripts/core/check-plugin-boundary.sh +45 -0
- package/scripts/core/check-skill-paths.sh +25 -0
- package/scripts/core/clean.sh +36 -0
- package/scripts/core/install-check.sh +93 -0
- package/scripts/core/regen-claude-copies.sh +26 -0
- package/scripts/core/regen-indexes.sh +10 -0
- package/scripts/core/regen-skill-references.sh +27 -0
- package/scripts/core/snapshot.sh +132 -0
- package/scripts/core/update.sh +35 -0
- package/scripts/core/verify.sh +201 -0
- package/scripts/docs/list.sh +129 -0
- package/scripts/gov/list.sh +234 -0
- package/scripts/lib/frontmatter.sh +30 -0
- package/scripts/lib/gov.sh +14 -0
- package/scripts/lib/sandbox-fixtures.sh +109 -0
- package/scripts/lib/sandbox-git.sh +73 -0
- package/scripts/lib/tooling.sh +24 -0
- package/scripts/lib/ui.sh +173 -0
- package/scripts/lib/worktree.sh +20 -0
- package/scripts/manage-sandbox.sh +453 -0
- package/scripts/snippets/create.sh +156 -0
- package/scripts/standards/list.sh +91 -0
- package/scripts/tooling/create.sh +109 -0
- package/scripts/tooling/ref.sh +141 -0
- package/scripts/tooling/verify.sh +179 -0
- package/snippets/claude/decision-memo.md +39 -0
- package/snippets/claude/feature-recap.md +19 -0
- package/snippets/claude/figma-steps.md +18 -0
- package/snippets/claude/orchestrator-resume.md +23 -0
- package/snippets/claude/orchestrator-sweep.md +10 -0
- package/snippets/compact-summary.md +5 -0
- package/snippets/create-snippet.md +7 -0
- package/snippets/decision-help.md +6 -0
- package/snippets/meta-prompt.md +14 -0
- package/snippets/research-prompt.md +7 -0
- package/snippets/session-notes.md +11 -0
- package/snippets/snippets.toml +6 -0
- package/snippets/step-by-step.md +10 -0
- package/snippets/web-research.md +21 -0
- package/src/claude/gitignore.ts +51 -0
- package/src/claude/seeds-list.ts +47 -0
- package/src/claude/seeds.ts +124 -0
- package/src/claude/settings.ts +151 -0
- package/src/cli-run.ts +43 -0
- package/src/cli.ts +111 -0
- package/src/commands/claude.ts +349 -0
- package/src/commands/design.ts +39 -0
- package/src/commands/docs.ts +59 -0
- package/src/commands/feedback-format.ts +23 -0
- package/src/commands/feedback.ts +103 -0
- package/src/commands/gov.ts +268 -0
- package/src/commands/indexes.ts +182 -0
- package/src/commands/init.ts +117 -0
- package/src/commands/pass-through.ts +39 -0
- package/src/commands/sandbox.ts +315 -0
- package/src/commands/slides.ts +106 -0
- package/src/commands/snippets.ts +236 -0
- package/src/commands/standards.ts +89 -0
- package/src/commands/sync.ts +211 -0
- package/src/commands/tasks.ts +185 -0
- package/src/commands/tooling.ts +432 -0
- package/src/commands/transcripts.ts +48 -0
- package/src/commands/wiki.ts +101 -0
- package/src/copy.ts +30 -0
- package/src/design/parse.ts +79 -0
- package/src/design/render.ts +170 -0
- package/src/docs/read.ts +59 -0
- package/src/exec.ts +17 -0
- package/src/frontmatter.ts +13 -0
- package/src/github-format.ts +13 -0
- package/src/github.ts +20 -0
- package/src/gov/adapter.ts +73 -0
- package/src/gov/install.ts +103 -0
- package/src/gov/payload.ts +39 -0
- package/src/gov/stacks.ts +124 -0
- package/src/indexes/frontmatter.ts +46 -0
- package/src/indexes/regen.ts +84 -0
- package/src/indexes/render.ts +181 -0
- package/src/indexes/walk.ts +111 -0
- package/src/init/flags.ts +66 -0
- package/src/init/plan.ts +128 -0
- package/src/init/run.ts +46 -0
- package/src/init/steps.ts +91 -0
- package/src/sandbox/coverage.ts +115 -0
- package/src/sandbox/expect.ts +412 -0
- package/src/slides/layouts.ts +391 -0
- package/src/slides/open.ts +18 -0
- package/src/slides/parse.ts +84 -0
- package/src/slides/render.ts +88 -0
- package/src/slides/styles.ts +44 -0
- package/src/snippets/adapter.ts +34 -0
- package/src/snippets/categories.ts +59 -0
- package/src/snippets/install.ts +125 -0
- package/src/snippets/list.ts +32 -0
- package/src/snippets/presets.ts +50 -0
- package/src/standards/adapter.ts +51 -0
- package/src/standards/index-refresh.ts +44 -0
- package/src/standards/install.ts +52 -0
- package/src/sync/check.ts +269 -0
- package/src/sync/engine.ts +416 -0
- package/src/sync/git.ts +204 -0
- package/src/sync/stamp.ts +202 -0
- package/src/sync/target.ts +79 -0
- package/src/sync/workflow.ts +201 -0
- package/src/target.ts +43 -0
- package/src/tasks/archive.ts +304 -0
- package/src/tooling/gitignore.ts +122 -0
- package/src/tooling/inject.ts +214 -0
- package/src/tooling/list.ts +39 -0
- package/src/tooling/manifest.ts +178 -0
- package/src/tooling/package.ts +166 -0
- package/src/tooling/scan.ts +186 -0
- package/src/transcripts/fetch.ts +156 -0
- package/src/transcripts/metadata.ts +54 -0
- package/src/transcripts/vtt.ts +114 -0
- package/src/ui.ts +187 -0
- package/src/wiki/init.ts +85 -0
- package/standards/architecture.md +41 -0
- package/standards/bundled/branch.md +49 -0
- package/standards/bundled/commit.md +63 -0
- package/standards/bundled/issue.md +84 -0
- package/standards/bundled/pr.md +124 -0
- package/standards/bundled/roadmap.md +52 -0
- package/standards/bundled/snippets.md +57 -0
- package/standards/bundled/standard.md +52 -0
- package/standards/context.md +132 -0
- package/standards/design.md +31 -0
- package/standards/diagrams.md +55 -0
- package/standards/index.md +21 -0
- package/standards/prose.md +122 -0
- package/standards/readme.md +163 -0
- package/standards/requirements.md +61 -0
- package/standards/rule.md +79 -0
- package/standards/skill.md +257 -0
- package/standards/tasks.md +140 -0
- package/standards/versioning.md +47 -0
- package/standards/wireframes.md +67 -0
- package/tooling/astro/configs/astro.config.mjs +17 -0
- package/tooling/astro/configs/eslint.config.js +79 -0
- package/tooling/astro/configs/playwright.config.ts +25 -0
- package/tooling/astro/configs/tsconfig.json +12 -0
- package/tooling/astro/configs/vitest.config.ts +22 -0
- package/tooling/astro/manifest.toml +32 -0
- package/tooling/astro/reference.md +60 -0
- package/tooling/base/configs/.editorconfig +5 -0
- package/tooling/base/configs/.github/pull_request_template.md +18 -0
- package/tooling/base/configs/.github/workflows/verify.yml +35 -0
- package/tooling/base/configs/.husky/commit-msg +1 -0
- package/tooling/base/configs/.husky/post-merge +61 -0
- package/tooling/base/configs/.husky/post-rewrite +21 -0
- package/tooling/base/configs/.husky/pre-commit +1 -0
- package/tooling/base/configs/.husky/pre-push +1 -0
- package/tooling/base/configs/.prettierrc +12 -0
- package/tooling/base/configs/.shellcheckrc +1 -0
- package/tooling/base/configs/.vscode/extensions.json +9 -0
- package/tooling/base/configs/.vscode/settings.json +3 -0
- package/tooling/base/configs/commitlint.config.js +11 -0
- package/tooling/base/configs/scripts/clean.sh +45 -0
- package/tooling/base/configs/scripts/update.sh +49 -0
- package/tooling/base/configs/scripts/verify.sh +64 -0
- package/tooling/base/manifest.toml +32 -0
- package/tooling/base/reference.md +114 -0
- package/tooling/base/seeds/.claude/context/ci.md +27 -0
- package/tooling/base/seeds/.claude/context/development.md +32 -0
- package/tooling/base/seeds/.cspell/project-terms.txt +0 -0
- package/tooling/base/seeds/.cspell/tech-stack.txt +19 -0
- package/tooling/base/seeds/.lintstagedrc +8 -0
- package/tooling/base/seeds/.prettierignore +0 -0
- package/tooling/base/seeds/cspell.json +20 -0
- package/tooling/claude/manifest.toml +11 -0
- package/tooling/claude/reference.md +62 -0
- package/tooling/claude/seeds/.claude/ARCHITECTURE.md +13 -0
- package/tooling/claude/seeds/.claude/DESIGN.md +62 -0
- package/tooling/claude/seeds/.claude/REQUIREMENTS.md +18 -0
- package/tooling/claude/seeds/.claude/context/index.md +8 -0
- package/tooling/claude/seeds/.claude/hooks/index-reminder.sh +43 -0
- package/tooling/claude/seeds/.claude/hooks/scratch-guard.sh +45 -0
- package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +61 -0
- package/tooling/claude/seeds/.claude/hooks/tasks-index.sh +60 -0
- package/tooling/claude/seeds/.claude/settings.json +39 -0
- package/tooling/claude/seeds/.claude/tasks/index.md +8 -0
- package/tooling/claude/seeds/.claude/wireframes/index.md +8 -0
- package/tooling/claude/seeds/CLAUDE.md +87 -0
- package/tooling/claude/user/settings.template.json +10 -0
- package/tooling/claude/user/statusline-command.sh +53 -0
- package/tooling/python/configs/.coveragerc +14 -0
- package/tooling/python/configs/.python-version +1 -0
- package/tooling/python/configs/mypy.ini +6 -0
- package/tooling/python/configs/pytest.ini +4 -0
- package/tooling/python/configs/ruff.toml +15 -0
- package/tooling/python/configs/scripts/verify.sh +77 -0
- package/tooling/python/manifest.toml +16 -0
- package/tooling/python/reference.md +66 -0
- package/tooling/python/seeds/.cspell/tech-stack.txt +19 -0
- package/tooling/python/seeds/tests/test_smoke.py +2 -0
- package/tooling/vite-react/configs/playwright.config.ts +25 -0
- package/tooling/vite-react/configs/tsconfig.json +35 -0
- package/tooling/vite-react/configs/vite.config.ts +14 -0
- package/tooling/vite-react/configs/vitest.config.ts +26 -0
- package/tooling/vite-react/manifest.toml +21 -0
- package/tooling/vite-react/reference.md +55 -0
- package/tooling/vite-react/seeds/.cspell/project-terms.txt +1 -0
- package/tooling/vite-react/seeds/.cspell/tech-stack.txt +1 -0
- package/tooling/web/configs/.github/workflows/verify.yml +134 -0
- package/tooling/web/configs/.vscode/extensions.json +13 -0
- package/tooling/web/configs/.vscode/settings.json +10 -0
- package/tooling/web/configs/e2e/home.spec.ts +6 -0
- package/tooling/web/configs/e2e/screenshot.ts +41 -0
- package/tooling/web/configs/eslint.config.js +82 -0
- package/tooling/web/configs/scripts/screenshot.sh +28 -0
- package/tooling/web/configs/scripts/verify.sh +80 -0
- package/tooling/web/configs/src/test/setup.ts +8 -0
- package/tooling/web/manifest.toml +57 -0
- package/tooling/web/reference.md +95 -0
- package/tooling/web/seeds/.cspell/tech-stack.txt +18 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { mergeSections } from '@/tooling/gitignore'
|
|
4
|
+
import { type Manifest, resolveChain } from '@/tooling/manifest'
|
|
5
|
+
|
|
6
|
+
export const CLAUDE_STACK = 'claude'
|
|
7
|
+
|
|
8
|
+
export interface GitignoreEntry {
|
|
9
|
+
readonly entry: string
|
|
10
|
+
readonly present: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function claudeChain(root: string): Manifest[] {
|
|
14
|
+
return resolveChain(root, CLAUDE_STACK)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Previews the gitignore merge without writing. The answer comes from
|
|
19
|
+
* `mergeSections`, the same function the apply step runs, so the preview can
|
|
20
|
+
* never disagree with what lands.
|
|
21
|
+
*
|
|
22
|
+
* The bash matched the manifest's `[gitignore]` table with a line regex that
|
|
23
|
+
* required the array to open and close on one line, and it re-parsed TOML that
|
|
24
|
+
* `loadManifest` already reads. Routing through the manifest loader drops both
|
|
25
|
+
* problems.
|
|
26
|
+
*/
|
|
27
|
+
export function planGitignore(
|
|
28
|
+
chain: readonly Manifest[],
|
|
29
|
+
target: string,
|
|
30
|
+
): GitignoreEntry[] {
|
|
31
|
+
const path = join(target, '.gitignore')
|
|
32
|
+
const content = existsSync(path) ? readFileSync(path, 'utf8') : ''
|
|
33
|
+
const entries: GitignoreEntry[] = []
|
|
34
|
+
|
|
35
|
+
for (const manifest of chain) {
|
|
36
|
+
const added = new Set(mergeSections(content, manifest.gitignore).added)
|
|
37
|
+
for (const section of manifest.gitignore) {
|
|
38
|
+
for (const entry of section.entries) {
|
|
39
|
+
entries.push({ entry, present: !added.has(entry) })
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return entries
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function pendingEntries(
|
|
48
|
+
entries: readonly GitignoreEntry[],
|
|
49
|
+
): GitignoreEntry[] {
|
|
50
|
+
return entries.filter((entry) => !entry.present)
|
|
51
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises'
|
|
2
|
+
import { relative } from 'node:path'
|
|
3
|
+
import { planSeeds } from '@/claude/seeds'
|
|
4
|
+
|
|
5
|
+
export interface SeedListing {
|
|
6
|
+
readonly name: string
|
|
7
|
+
readonly source: string
|
|
8
|
+
readonly target: string
|
|
9
|
+
readonly src: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface SeedListingWithContent {
|
|
13
|
+
readonly name: string
|
|
14
|
+
readonly source: string
|
|
15
|
+
readonly target: string
|
|
16
|
+
readonly content: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Reads the same plan `aitk claude init` applies. The bash re-globbed the seeds
|
|
21
|
+
* directory with its own hard-coded subdirectory list, which had drifted: it
|
|
22
|
+
* never listed `.claude/context/`, so a seed init installs went unreported.
|
|
23
|
+
*
|
|
24
|
+
* The target is irrelevant to a listing, so it resolves against the source
|
|
25
|
+
* root and only the source-side fields are read.
|
|
26
|
+
*/
|
|
27
|
+
export function listSeeds(root: string): SeedListing[] {
|
|
28
|
+
return planSeeds(root, root).map(({ seed }) => ({
|
|
29
|
+
name: seed.scanLabel,
|
|
30
|
+
source: relative(root, seed.src),
|
|
31
|
+
target: seed.applyLabel,
|
|
32
|
+
src: seed.src,
|
|
33
|
+
}))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function readSeedContents(
|
|
37
|
+
listings: readonly SeedListing[],
|
|
38
|
+
): Promise<SeedListingWithContent[]> {
|
|
39
|
+
return Promise.all(
|
|
40
|
+
listings.map(async ({ name, source, target, src }) => ({
|
|
41
|
+
name,
|
|
42
|
+
source,
|
|
43
|
+
target,
|
|
44
|
+
content: await readFile(src, 'utf8'),
|
|
45
|
+
})),
|
|
46
|
+
)
|
|
47
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import { chmod } from 'node:fs/promises'
|
|
3
|
+
import { join } from 'node:path'
|
|
4
|
+
import { copyPreservingMode } from '@/copy'
|
|
5
|
+
|
|
6
|
+
const SEEDS_DIR = join('tooling', 'claude', 'seeds')
|
|
7
|
+
const CLAUDE_DIR = '.claude'
|
|
8
|
+
const CLAUDE_MD = 'CLAUDE.md'
|
|
9
|
+
const HOOKS = 'hooks'
|
|
10
|
+
const SUBDIRS: readonly string[] = [HOOKS, 'context', 'tasks', 'wireframes']
|
|
11
|
+
|
|
12
|
+
export type SeedScope = 'claude' | 'root'
|
|
13
|
+
|
|
14
|
+
export interface Seed {
|
|
15
|
+
readonly src: string
|
|
16
|
+
readonly dest: string
|
|
17
|
+
readonly scanLabel: string
|
|
18
|
+
readonly applyLabel: string
|
|
19
|
+
readonly scope: SeedScope
|
|
20
|
+
readonly executable: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface SeedEntry {
|
|
24
|
+
readonly seed: Seed
|
|
25
|
+
readonly present: boolean
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface SeedCounts {
|
|
29
|
+
readonly claude: number
|
|
30
|
+
readonly root: number
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function seedsRoot(root: string): string {
|
|
34
|
+
return join(root, SEEDS_DIR)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Lists a single directory level, sorted the way `find -maxdepth 1 -type f |
|
|
39
|
+
* sort` was. Bun.Glob skips dotfiles without `dot`, and every path here sits
|
|
40
|
+
* under `.claude`, so omitting it would match nothing.
|
|
41
|
+
*/
|
|
42
|
+
function listLevel(dir: string): string[] {
|
|
43
|
+
if (!existsSync(dir)) return []
|
|
44
|
+
return [
|
|
45
|
+
...new Bun.Glob('*').scanSync({ cwd: dir, onlyFiles: true, dot: true }),
|
|
46
|
+
].sort()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Builds the seed list in the order the bash scanned it: the `.claude` root
|
|
51
|
+
* level, then each subdirectory, then the project-level `CLAUDE.md`. Order is
|
|
52
|
+
* load-bearing because it is also the order the timeline prints.
|
|
53
|
+
*/
|
|
54
|
+
export function planSeeds(root: string, target: string): SeedEntry[] {
|
|
55
|
+
const source = join(seedsRoot(root), CLAUDE_DIR)
|
|
56
|
+
const destDir = join(target, CLAUDE_DIR)
|
|
57
|
+
const seeds: Seed[] = []
|
|
58
|
+
|
|
59
|
+
for (const name of listLevel(source)) {
|
|
60
|
+
seeds.push({
|
|
61
|
+
src: join(source, name),
|
|
62
|
+
dest: join(destDir, name),
|
|
63
|
+
scanLabel: name,
|
|
64
|
+
applyLabel: join(CLAUDE_DIR, name),
|
|
65
|
+
scope: 'claude',
|
|
66
|
+
executable: false,
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
for (const subdir of SUBDIRS) {
|
|
71
|
+
for (const name of listLevel(join(source, subdir))) {
|
|
72
|
+
const rel = `${subdir}/${name}`
|
|
73
|
+
seeds.push({
|
|
74
|
+
src: join(source, subdir, name),
|
|
75
|
+
dest: join(destDir, subdir, name),
|
|
76
|
+
scanLabel: rel,
|
|
77
|
+
applyLabel: join(CLAUDE_DIR, subdir, name),
|
|
78
|
+
scope: 'claude',
|
|
79
|
+
executable: subdir === HOOKS,
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const claudeMd = join(seedsRoot(root), CLAUDE_MD)
|
|
85
|
+
if (existsSync(claudeMd)) {
|
|
86
|
+
seeds.push({
|
|
87
|
+
src: claudeMd,
|
|
88
|
+
dest: join(target, CLAUDE_MD),
|
|
89
|
+
scanLabel: CLAUDE_MD,
|
|
90
|
+
applyLabel: CLAUDE_MD,
|
|
91
|
+
scope: 'root',
|
|
92
|
+
executable: false,
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return seeds.map((seed) => ({ seed, present: existsSync(seed.dest) }))
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function pendingSeeds(entries: readonly SeedEntry[]): Seed[] {
|
|
100
|
+
return entries.filter((entry) => !entry.present).map((entry) => entry.seed)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function countByScope(seeds: readonly Seed[]): SeedCounts {
|
|
104
|
+
return {
|
|
105
|
+
claude: seeds.filter((seed) => seed.scope === 'claude').length,
|
|
106
|
+
root: seeds.filter((seed) => seed.scope === 'root').length,
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Copies each pending seed. Hooks get the executable bit the way `chmod +x`
|
|
112
|
+
* granted it, added on top of whatever mode the destination already carried.
|
|
113
|
+
*/
|
|
114
|
+
export async function applySeeds(seeds: readonly Seed[]): Promise<string[]> {
|
|
115
|
+
const applied: string[] = []
|
|
116
|
+
|
|
117
|
+
for (const seed of seeds) {
|
|
118
|
+
await copyPreservingMode(seed.src, seed.dest)
|
|
119
|
+
if (seed.executable) await chmod(seed.dest, 0o755)
|
|
120
|
+
applied.push(seed.applyLabel)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return applied
|
|
124
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import { chmod, mkdir, readFile, stat, writeFile } from 'node:fs/promises'
|
|
3
|
+
import { dirname } from 'node:path'
|
|
4
|
+
|
|
5
|
+
const DEFAULT_INDENT = ' '
|
|
6
|
+
const INDENT = /^([ \t]+)\S/m
|
|
7
|
+
|
|
8
|
+
export type SettingsRecord = Record<string, unknown>
|
|
9
|
+
|
|
10
|
+
export interface SettingsKey {
|
|
11
|
+
readonly label: string
|
|
12
|
+
readonly changed: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface SettingsPlan {
|
|
16
|
+
readonly keys: readonly SettingsKey[]
|
|
17
|
+
readonly next: SettingsRecord
|
|
18
|
+
readonly changed: boolean
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Reads the indentation of the first indented line. Rewriting an operator's
|
|
23
|
+
* settings file at a different width is a diff they did not ask for, and this
|
|
24
|
+
* verb is the only one in the toolkit that writes outside a target.
|
|
25
|
+
*/
|
|
26
|
+
export function detectIndent(source: string): string {
|
|
27
|
+
return INDENT.exec(source)?.[1] ?? DEFAULT_INDENT
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function serializeSettings(
|
|
31
|
+
value: SettingsRecord,
|
|
32
|
+
indent: string,
|
|
33
|
+
): string {
|
|
34
|
+
return `${JSON.stringify(value, null, indent)}\n`
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Parses a settings file, treating an absent one as empty. A malformed one
|
|
39
|
+
* throws rather than resolving to empty, because the alternative silently
|
|
40
|
+
* replaces a file the operator owns with a generated one.
|
|
41
|
+
*/
|
|
42
|
+
export async function readSettings(
|
|
43
|
+
path: string,
|
|
44
|
+
): Promise<{ value: SettingsRecord; indent: string }> {
|
|
45
|
+
if (!existsSync(path)) return { value: {}, indent: DEFAULT_INDENT }
|
|
46
|
+
|
|
47
|
+
const source = await readFile(path, 'utf8')
|
|
48
|
+
const indent = detectIndent(source)
|
|
49
|
+
if (source.trim() === '') return { value: {}, indent }
|
|
50
|
+
|
|
51
|
+
let parsed: unknown
|
|
52
|
+
try {
|
|
53
|
+
parsed = JSON.parse(source)
|
|
54
|
+
} catch (cause) {
|
|
55
|
+
throw new Error(`${path} is not valid JSON`, { cause })
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
59
|
+
throw new Error(`${path} is not a JSON object`)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return { value: parsed as SettingsRecord, indent }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function asRecord(value: unknown): SettingsRecord {
|
|
66
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
67
|
+
return {}
|
|
68
|
+
}
|
|
69
|
+
return value as SettingsRecord
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function asStrings(value: unknown): string[] {
|
|
73
|
+
if (!Array.isArray(value)) return []
|
|
74
|
+
return value.filter((entry): entry is string => typeof entry === 'string')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function equals(left: unknown, right: unknown): boolean {
|
|
78
|
+
return Bun.deepEquals(left, right)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Unions two permission lists into the sorted, deduplicated shape `jq unique`
|
|
83
|
+
* produced. The sort is load-bearing, since the comparison that decides
|
|
84
|
+
* whether to write runs against the sorted result.
|
|
85
|
+
*/
|
|
86
|
+
function mergeList(current: unknown, incoming: unknown): string[] {
|
|
87
|
+
return [...new Set([...asStrings(current), ...asStrings(incoming)])].sort()
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Applies the four settings the toolkit owns, leaving every other key in
|
|
92
|
+
* place. Each key reports whether it changed so the caller prints `+` or `✓`
|
|
93
|
+
* per key, matching the four separate `jq` passes this replaced.
|
|
94
|
+
*/
|
|
95
|
+
export function planSettings(
|
|
96
|
+
current: SettingsRecord,
|
|
97
|
+
template: SettingsRecord,
|
|
98
|
+
statusLineCommand: string,
|
|
99
|
+
): SettingsPlan {
|
|
100
|
+
const next: SettingsRecord = { ...current }
|
|
101
|
+
const keys: SettingsKey[] = []
|
|
102
|
+
|
|
103
|
+
const statusLine = asRecord(next.statusLine)
|
|
104
|
+
const statusLineChanged = statusLine.command !== statusLineCommand
|
|
105
|
+
if (statusLineChanged) {
|
|
106
|
+
next.statusLine = { type: 'command', command: statusLineCommand }
|
|
107
|
+
}
|
|
108
|
+
keys.push({ label: 'statusLine', changed: statusLineChanged })
|
|
109
|
+
|
|
110
|
+
const attribution = template.attribution
|
|
111
|
+
const attributionChanged = !equals(next.attribution, attribution)
|
|
112
|
+
if (attributionChanged) next.attribution = attribution
|
|
113
|
+
keys.push({ label: 'attribution', changed: attributionChanged })
|
|
114
|
+
|
|
115
|
+
const permissions = asRecord(next.permissions)
|
|
116
|
+
const merged: SettingsRecord = { ...permissions }
|
|
117
|
+
const templatePermissions = asRecord(template.permissions)
|
|
118
|
+
|
|
119
|
+
for (const field of ['allow', 'deny'] as const) {
|
|
120
|
+
const union = mergeList(permissions[field], templatePermissions[field])
|
|
121
|
+
const changed = !equals(asStrings(permissions[field]), union)
|
|
122
|
+
if (changed) merged[field] = union
|
|
123
|
+
keys.push({ label: `permissions.${field}`, changed })
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (keys.some((key) => key.label.startsWith('permissions.') && key.changed)) {
|
|
127
|
+
next.permissions = merged
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return { keys, next, changed: keys.some((key) => key.changed) }
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Writes in place, restoring the file's existing mode. The bash wrote through
|
|
135
|
+
* `mktemp` and `mv`, which handed the destination the temp file's 600 and
|
|
136
|
+
* silently tightened a settings file the operator had left at 644.
|
|
137
|
+
*/
|
|
138
|
+
export async function writeSettings(
|
|
139
|
+
path: string,
|
|
140
|
+
content: string,
|
|
141
|
+
): Promise<void> {
|
|
142
|
+
await mkdir(dirname(path), { recursive: true })
|
|
143
|
+
|
|
144
|
+
const mode = await stat(path)
|
|
145
|
+
.then((info) => info.mode)
|
|
146
|
+
.catch(() => undefined)
|
|
147
|
+
|
|
148
|
+
await writeFile(path, content)
|
|
149
|
+
|
|
150
|
+
if (mode !== undefined) await chmod(path, mode)
|
|
151
|
+
}
|
package/src/cli-run.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { join } from 'node:path'
|
|
2
|
+
import { execa } from 'execa'
|
|
3
|
+
|
|
4
|
+
export interface CliRunOptions {
|
|
5
|
+
/** Sets `AITK_NON_INTERACTIVE=1` for the child. Defaults to false. */
|
|
6
|
+
readonly nonInteractive?: boolean
|
|
7
|
+
/** Defaults to `inherit`, so a child prompt still reaches the operator. */
|
|
8
|
+
readonly stdin?: 'ignore' | 'inherit'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function cliPath(root: string): string {
|
|
12
|
+
return join(root, 'src', 'cli.ts')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Spawns an `aitk` subcommand as its own process, by path rather than through
|
|
17
|
+
* the global binary, so a linked worktree exercises its own code.
|
|
18
|
+
*
|
|
19
|
+
* Both callers want a separately failable child rather than an in-process call:
|
|
20
|
+
* `aitk init` reports each domain's outcome independently, and `aitk sync`
|
|
21
|
+
* relies on each domain opening its own frame. Returns whether the child
|
|
22
|
+
* succeeded rather than throwing, because a failed domain is a reportable
|
|
23
|
+
* outcome and not an abort.
|
|
24
|
+
*/
|
|
25
|
+
export function cliRun(
|
|
26
|
+
path: string,
|
|
27
|
+
args: readonly string[],
|
|
28
|
+
options: CliRunOptions = {},
|
|
29
|
+
): () => Promise<boolean> {
|
|
30
|
+
return async () => {
|
|
31
|
+
const env = options.nonInteractive
|
|
32
|
+
? { ...process.env, AITK_NON_INTERACTIVE: '1' }
|
|
33
|
+
: process.env
|
|
34
|
+
|
|
35
|
+
const result = await execa('bun', [path, ...args], {
|
|
36
|
+
stdio: [options.stdin ?? 'inherit', 'inherit', 'inherit'],
|
|
37
|
+
env,
|
|
38
|
+
reject: false,
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
return result.exitCode === 0
|
|
42
|
+
}
|
|
43
|
+
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { Command } from 'commander'
|
|
4
|
+
import { register as init } from '@/commands/init'
|
|
5
|
+
import { register as sandbox } from '@/commands/sandbox'
|
|
6
|
+
import { register as sync } from '@/commands/sync'
|
|
7
|
+
import { register as gov } from '@/commands/gov'
|
|
8
|
+
import { register as standards } from '@/commands/standards'
|
|
9
|
+
import { register as snippets } from '@/commands/snippets'
|
|
10
|
+
import { register as tooling } from '@/commands/tooling'
|
|
11
|
+
import { register as claude } from '@/commands/claude'
|
|
12
|
+
import { register as wiki } from '@/commands/wiki'
|
|
13
|
+
import { register as indexes } from '@/commands/indexes'
|
|
14
|
+
import { register as docs } from '@/commands/docs'
|
|
15
|
+
import { register as design } from '@/commands/design'
|
|
16
|
+
import { register as slides } from '@/commands/slides'
|
|
17
|
+
import { register as feedback } from '@/commands/feedback'
|
|
18
|
+
import { register as transcripts } from '@/commands/transcripts'
|
|
19
|
+
import { register as tasks } from '@/commands/tasks'
|
|
20
|
+
|
|
21
|
+
const GREY = '\x1b[0;90m'
|
|
22
|
+
const WHITE = '\x1b[1;37m'
|
|
23
|
+
const NC = '\x1b[0m'
|
|
24
|
+
|
|
25
|
+
function showHelp(): void {
|
|
26
|
+
const lines = [
|
|
27
|
+
`${GREY}┌${NC}`,
|
|
28
|
+
`${GREY}├${NC} ${WHITE}Usage:${NC} aitk [command]`,
|
|
29
|
+
`${GREY}│${NC}`,
|
|
30
|
+
`${GREY}│${NC} ${WHITE}Commands:${NC}`,
|
|
31
|
+
`${GREY}│${NC} init [path] ${GREY}# Bootstrap a project with toolkit domains${NC}`,
|
|
32
|
+
`${GREY}│${NC} sync [path] ${GREY}# Sync all installed domains in a project${NC}`,
|
|
33
|
+
`${GREY}│${NC} sandbox [cat:cmd] ${GREY}# Provision and run sandbox scenarios${NC}`,
|
|
34
|
+
`${GREY}│${NC} gov [command] ${GREY}# Governance commands (install, sync)${NC}`,
|
|
35
|
+
`${GREY}│${NC} standards [cmd] ${GREY}# Standards commands (install, sync)${NC}`,
|
|
36
|
+
`${GREY}│${NC} snippets [cmd] ${GREY}# Snippets commands (install, sync)${NC}`,
|
|
37
|
+
`${GREY}│${NC} tooling [cmd] ${GREY}# Manage tooling stacks (sync, ref, create)${NC}`,
|
|
38
|
+
`${GREY}│${NC} claude [cmd] ${GREY}# Claude workflow (init, sync, setup)${NC}`,
|
|
39
|
+
`${GREY}│${NC} wiki [cmd] ${GREY}# Wiki commands (init)${NC}`,
|
|
40
|
+
`${GREY}│${NC} indexes [cmd] ${GREY}# Regenerate index.md files (regen)${NC}`,
|
|
41
|
+
`${GREY}│${NC} docs [cmd|topic] ${GREY}# Emit toolkit reference docs (list, <topic>)${NC}`,
|
|
42
|
+
`${GREY}│${NC} design [cmd] ${GREY}# Design system commands (render)${NC}`,
|
|
43
|
+
`${GREY}│${NC} slides [cmd] ${GREY}# Slide deck commands (render, list)${NC}`,
|
|
44
|
+
`${GREY}│${NC} feedback ${GREY}# Write toolkit feedback from stdin to .claude/review/${NC}`,
|
|
45
|
+
`${GREY}│${NC} transcripts <url> ${GREY}# Fetch a YouTube transcript with metadata frontmatter${NC}`,
|
|
46
|
+
`${GREY}│${NC} tasks [cmd] ${GREY}# Task board commands (archive)${NC}`,
|
|
47
|
+
`${GREY}│${NC}`,
|
|
48
|
+
`${GREY}│${NC} ${WHITE}Sandbox:${NC}`,
|
|
49
|
+
`${GREY}│${NC} aitk sandbox ${GREY}# Interactive scenario picker${NC}`,
|
|
50
|
+
`${GREY}│${NC} aitk sandbox git:commit ${GREY}# Run specific scenario${NC}`,
|
|
51
|
+
`${GREY}│${NC} aitk sandbox reset ${GREY}# Reset sandbox to baseline${NC}`,
|
|
52
|
+
`${GREY}│${NC} aitk sandbox clean ${GREY}# Wipe the sandbox${NC}`,
|
|
53
|
+
`${GREY}│${NC}`,
|
|
54
|
+
`${GREY}│${NC} ${WHITE}Examples:${NC}`,
|
|
55
|
+
`${GREY}│${NC} aitk sync ../my-app`,
|
|
56
|
+
`${GREY}│${NC} aitk sandbox git:commit`,
|
|
57
|
+
`${GREY}│${NC} aitk gov install react`,
|
|
58
|
+
`${GREY}│${NC} aitk gov sync ../my-app`,
|
|
59
|
+
`${GREY}│${NC} aitk standards sync ../my-app`,
|
|
60
|
+
`${GREY}│${NC} aitk snippets install base ../my-app`,
|
|
61
|
+
`${GREY}│${NC} aitk snippets sync ../my-app`,
|
|
62
|
+
`${GREY}│${NC} aitk init ../my-app`,
|
|
63
|
+
`${GREY}│${NC} aitk tooling sync base`,
|
|
64
|
+
`${GREY}│${NC} aitk tooling create`,
|
|
65
|
+
`${GREY}│${NC} aitk claude init`,
|
|
66
|
+
`${GREY}│${NC} aitk indexes regen`,
|
|
67
|
+
`${GREY}│${NC} aitk indexes regen --dry-run --json`,
|
|
68
|
+
`${GREY}│${NC} aitk docs list --json`,
|
|
69
|
+
`${GREY}│${NC} aitk docs agents`,
|
|
70
|
+
`${GREY}│${NC} aitk design render`,
|
|
71
|
+
`${GREY}│${NC} aitk slides render`,
|
|
72
|
+
`${GREY}│${NC} aitk slides list --json`,
|
|
73
|
+
`${GREY}│${NC} pbpaste | aitk feedback`,
|
|
74
|
+
`${GREY}│${NC} aitk transcripts https://youtu.be/VIDEO_ID`,
|
|
75
|
+
`${GREY}│${NC} aitk tasks archive --pull-request 673 --json`,
|
|
76
|
+
`${GREY}└${NC}`,
|
|
77
|
+
]
|
|
78
|
+
console.log(lines.join('\n'))
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const program = new Command()
|
|
82
|
+
program
|
|
83
|
+
.name('aitk')
|
|
84
|
+
.version('0.1.0')
|
|
85
|
+
.enablePositionalOptions()
|
|
86
|
+
.helpOption(false)
|
|
87
|
+
program.action(() => showHelp())
|
|
88
|
+
program.on('option:help', () => {
|
|
89
|
+
showHelp()
|
|
90
|
+
process.exit(0)
|
|
91
|
+
})
|
|
92
|
+
program.option('-h, --help', 'Show help')
|
|
93
|
+
|
|
94
|
+
init(program)
|
|
95
|
+
sandbox(program)
|
|
96
|
+
sync(program)
|
|
97
|
+
gov(program)
|
|
98
|
+
standards(program)
|
|
99
|
+
snippets(program)
|
|
100
|
+
tooling(program)
|
|
101
|
+
claude(program)
|
|
102
|
+
wiki(program)
|
|
103
|
+
indexes(program)
|
|
104
|
+
docs(program)
|
|
105
|
+
design(program)
|
|
106
|
+
slides(program)
|
|
107
|
+
feedback(program)
|
|
108
|
+
transcripts(program)
|
|
109
|
+
tasks(program)
|
|
110
|
+
|
|
111
|
+
program.parse()
|