@alavida/agentpack 0.1.4 → 0.1.6

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/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "@alavida/agentpack",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Package-backed skills lifecycle CLI for agent skills and plugins",
5
5
  "type": "module",
6
+ "workspaces": [
7
+ "packages/*"
8
+ ],
6
9
  "bin": {
7
10
  "agentpack": "bin/agentpack.js",
8
11
  "intent": "bin/intent.js"
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: agentpack-cli
3
3
  description: Use the agentpack CLI correctly when treating knowledge as a package. Apply the authored skill lifecycle, plugin lifecycle, source-backed validation, install flow, and bundled plugin artifact flow without mixing those stages together.
4
- library_version: 0.1.3
4
+ library_version: 0.1.4
5
5
  sources:
6
6
  - README.md
7
7
  - docs/introduction.mdx
@@ -20,7 +20,8 @@ Use this skill when the user is working with `@alavida/agentpack` and needs the
20
20
 
21
21
  Agentpack is a lifecycle toolchain for agent artifacts:
22
22
 
23
- - a packaged skill is a reusable capability artifact
23
+ - a package is the distribution unit
24
+ - an exported skill is the runtime module unit
24
25
  - a plugin package is a deployable runtime shell
25
26
  - source docs are the truth
26
27
  - `SKILL.md` is the compiled agent-facing artifact
@@ -49,19 +50,20 @@ If a skill points at `domains/.../knowledge/*.md`, run `skills validate`, `skill
49
50
 
50
51
  ### 1. Authored packaged skill
51
52
 
52
- Use when the user is creating or editing one reusable skill package.
53
+ Use when the user is creating or editing one packaged skill module or a package that exports several skill modules.
53
54
 
54
55
  Default flow:
55
56
 
56
- - `agentpack skills inspect <skill-dir>`
57
- - `agentpack skills validate <skill-dir>`
58
- - `agentpack skills dev <skill-dir>` if local runtime testing is needed
59
- - `agentpack skills dev --no-dashboard <skill-dir>` if the user wants to skip the local workbench
57
+ - `agentpack skills inspect <target>`
58
+ - `agentpack skills validate <target>`
59
+ - `agentpack skills dev <target>` if local runtime testing is needed
60
+ - `agentpack skills dev --no-dashboard <target>` if the user wants to skip the local workbench
60
61
 
61
62
  Key idea:
62
63
 
63
- - `SKILL.md.requires` is the source of truth
64
- - `package.json.dependencies` is the compiled mirror
64
+ - `package.json.agentpack.skills` declares exported skill modules
65
+ - `SKILL.md.requires` is the source of truth for skill-to-skill edges
66
+ - `package.json.dependencies` is the managed cross-package mirror
65
67
  - `validate` and `dev` sync dependencies automatically
66
68
  - `skills validate` records the current source-hash snapshot in `.agentpack/build-state.json`
67
69
  - `skills dev` materializes the compiled skill artifact for runtime use
@@ -77,7 +79,7 @@ Persistence rule:
77
79
  Runtime notes:
78
80
 
79
81
  - after `skills dev` writes to `.claude/skills/` or `.agents/skills/`, start a fresh agent session if the current one was already running
80
- - `skills dev` starts a localhost workbench by default for one selected skill, with provenance edges, direct required skills, and actions like validate or stale checks
82
+ - `skills dev` starts a localhost workbench by default for one selected exported skill, with provenance edges, internal module edges, cross-package dependency edges, and actions like validate or stale checks
81
83
  - `skills dev` records the active session in `.agentpack/dev-session.json` so the next run can clean up stale runtime links after abnormal termination
82
84
  - if a stale local dev session blocks startup, use `agentpack skills dev cleanup` and escalate to `agentpack skills dev cleanup --force` only when the recorded pid is a false positive
83
85
  - use `agentpack skills unlink <root> --recursive` when you need to remove one active dev root plus its transitive local runtime links
@@ -92,7 +94,7 @@ Use when the skill is already published and the user wants it available in anoth
92
94
 
93
95
  Default flow:
94
96
 
95
- - `agentpack skills install <package-name>`
97
+ - `agentpack skills install <package-name-or-local-package-path>`
96
98
  - `agentpack skills env`
97
99
 
98
100
  Do not prescribe `skills dev` here unless the user is authoring locally.
@@ -124,8 +126,8 @@ Use when the source docs changed and the user needs to know whether the packaged
124
126
  Default flow:
125
127
 
126
128
  - `agentpack skills stale`
127
- - `agentpack skills stale <skill>`
128
- - `agentpack skills validate <skill>`
129
+ - `agentpack skills stale <target>`
130
+ - `agentpack skills validate <target>`
129
131
 
130
132
  Key idea:
131
133
 
@@ -138,7 +140,8 @@ When the user is reasoning about the model itself, explain agentpack this way:
138
140
 
139
141
  - docs or knowledge files are source files
140
142
  - `SKILL.md` is the compiled artifact
141
- - `package.json` is the distribution manifest
143
+ - `package.json` is the package manifest and export table
144
+ - canonical skill ids look like `@scope/package:skill-name`
142
145
  - install and materialization are the runtime-resolution step
143
146
  - staleness means the source changed after the last known compiled state
144
147
 
@@ -7,10 +7,11 @@ Use this reference when the user needs the methodology behind packaged skills, n
7
7
  A packaged skill is a reusable capability artifact.
8
8
 
9
9
  - source docs or knowledge files are the truth
10
- - `SKILL.md` is the authored agent artifact
10
+ - `SKILL.md` is the authored agent artifact for one exported skill module
11
11
  - `package.json` is the package and distribution artifact
12
- - `requires` expresses direct skill dependencies
13
- - `package.json.dependencies` is the compiled mirror of `requires`
12
+ - `package.json.agentpack.skills` declares exported skill modules
13
+ - `requires` expresses direct skill dependencies using canonical ids like `@scope/package:skill-name`
14
+ - `package.json.dependencies` is the managed cross-package mirror of `requires`
14
15
 
15
16
  This is closer to a compiler pipeline than a prompt file:
16
17
 
@@ -22,27 +23,28 @@ This is closer to a compiler pipeline than a prompt file:
22
23
 
23
24
  ## Single Source Of Truth
24
25
 
25
- `SKILL.md.requires` is the dependency truth.
26
+ `SKILL.md.requires` is the dependency truth for skill-to-skill edges.
26
27
 
27
- Do not tell the user to hand-maintain `package.json.dependencies` as the primary dependency source. Agentpack treats those dependencies as a compiled mirror.
28
+ Do not tell the user to hand-maintain `package.json.dependencies` as the primary dependency source. Agentpack treats those dependencies as a compiled package-level mirror for cross-package references.
28
29
 
29
30
  Practical consequence:
30
31
 
31
32
  - if `requires` changes, run `skills validate` or `skills dev`
32
- - those commands sync the package dependencies automatically
33
+ - those commands sync cross-package package dependencies automatically
34
+ - same-package module references do not create package dependency entries
33
35
 
34
36
  ## Local Authoring Flow
35
37
 
36
38
  Use this when the user is creating or changing a packaged skill in the same repo as its source docs.
37
39
 
38
- 1. `agentpack skills inspect <skill-dir>`
39
- 2. `agentpack skills validate <skill-dir>`
40
- 3. `agentpack skills dev <skill-dir>` if the user wants agent runtime discovery during iteration
40
+ 1. `agentpack skills inspect <target>`
41
+ 2. `agentpack skills validate <target>`
42
+ 3. `agentpack skills dev <target>` if the user wants agent runtime discovery during iteration
41
43
 
42
44
  What each step means:
43
45
 
44
46
  - `inspect` explains what the skill currently is
45
- - `validate` checks package readiness, source existence, and records the validated source snapshot in `.agentpack/build-state.json`
47
+ - `validate` checks package readiness, exported skill declarations, source existence, canonical dependency resolution, and records the validated source snapshot in `.agentpack/build-state.json`
46
48
  - `dev` links the skill into `.claude/skills/` and `.agents/skills/` for local testing
47
49
 
48
50
  Important persistence behavior:
@@ -76,7 +78,7 @@ Authoring stage:
76
78
 
77
79
  Consumption stage:
78
80
 
79
- - package name
81
+ - package name or local package path
80
82
  - installed from registry or tarball
81
83
  - `skills install`
82
84
  - `skills env`
@@ -3,7 +3,7 @@ name: authoring-skillgraphs-from-knowledge
3
3
  description: Use when authoring packaged skills from source knowledge with valid SKILL.md metadata, package.json release fields, provenance sources, and requires edges in agentpack.
4
4
  type: core
5
5
  library: agentpack
6
- library_version: "0.1.3"
6
+ library_version: "0.1.4"
7
7
  sources:
8
8
  - "alavida-ai/agentpack:docs/commands.mdx"
9
9
  - "alavida-ai/agentpack:docs/architecture.mdx"
@@ -22,14 +22,22 @@ metadata:
22
22
  sources:
23
23
  - domains/value/knowledge/selling-points.md
24
24
  requires:
25
- - @alavida-ai/methodology-gary-provost
25
+ - "@alavida/methodology:gary-provost"
26
26
  ---
27
27
  ```
28
28
 
29
29
  ```json
30
30
  {
31
- "name": "@alavida-ai/value-copywriting",
31
+ "name": "@alavida/value-copywriting",
32
32
  "version": "1.0.0",
33
+ "files": ["skills"],
34
+ "agentpack": {
35
+ "skills": {
36
+ "value-copywriting": {
37
+ "path": "skills/value-copywriting/SKILL.md"
38
+ }
39
+ }
40
+ },
33
41
  "repository": {
34
42
  "type": "git",
35
43
  "url": "git+https://github.com/alavida-ai/knowledge-base.git"
@@ -37,9 +45,8 @@ requires:
37
45
  "publishConfig": {
38
46
  "registry": "https://npm.pkg.github.com"
39
47
  },
40
- "files": ["SKILL.md"],
41
48
  "dependencies": {
42
- "@alavida-ai/methodology-gary-provost": "^1.0.0"
49
+ "@alavida/methodology": "^1.0.0"
43
50
  }
44
51
  }
45
52
  ```
@@ -50,20 +57,20 @@ requires:
50
57
 
51
58
  ```yaml
52
59
  requires:
53
- - @alavida-ai/methodology-gary-provost
60
+ - "@alavida/methodology:gary-provost"
54
61
  ```
55
62
 
56
63
  ### Validate to sync and record provenance
57
64
 
58
65
  ```bash
59
- agentpack skills validate domains/value/skills/copywriting
66
+ agentpack skills validate domains/value/skills/value-copywriting
60
67
  ```
61
68
 
62
69
  ### Inspect by path or package name
63
70
 
64
71
  ```bash
65
- agentpack skills inspect domains/value/skills/copywriting
66
- agentpack skills inspect @alavida-ai/value-copywriting
72
+ agentpack skills inspect domains/value/skills/value-copywriting
73
+ agentpack skills inspect @alavida/value-copywriting:value-copywriting
67
74
  ```
68
75
 
69
76
  ## Common Mistakes
@@ -75,7 +82,7 @@ Wrong:
75
82
  ```json
76
83
  {
77
84
  "dependencies": {
78
- "@alavida-ai/methodology-gary-provost": "^1.0.0"
85
+ "@alavida/methodology": "^1.0.0"
79
86
  }
80
87
  }
81
88
  ```
@@ -84,10 +91,10 @@ Correct:
84
91
 
85
92
  ```yaml
86
93
  requires:
87
- - @alavida-ai/methodology-gary-provost
94
+ - "@alavida/methodology:gary-provost"
88
95
  ```
89
96
 
90
- `requires` is the authored dependency truth; `package.json.dependencies` is the compiled mirror.
97
+ `requires` is the authored dependency truth; `package.json.dependencies` is the managed cross-package mirror.
91
98
 
92
99
  Source: skills/agentpack-cli/SKILL.md
93
100
 
@@ -105,11 +112,18 @@ Correct:
105
112
 
106
113
  ```json
107
114
  {
108
- "files": ["SKILL.md"]
115
+ "files": ["skills"],
116
+ "agentpack": {
117
+ "skills": {
118
+ "value-copywriting": {
119
+ "path": "skills/value-copywriting/SKILL.md"
120
+ }
121
+ }
122
+ }
109
123
  }
110
124
  ```
111
125
 
112
- A package that excludes `SKILL.md` is structurally invalid even if the authored source exists locally.
126
+ A package that excludes its exported skill files is structurally invalid even if the authored source exists locally.
113
127
 
114
128
  Source: docs/commands.mdx
115
129
 
@@ -119,7 +133,7 @@ Wrong:
119
133
 
120
134
  ```json
121
135
  {
122
- "name": "@alavida-ai/value-copywriting"
136
+ "name": "@alavida/value-copywriting"
123
137
  }
124
138
  ```
125
139
 
@@ -127,8 +141,15 @@ Correct:
127
141
 
128
142
  ```json
129
143
  {
130
- "name": "@alavida-ai/value-copywriting",
144
+ "name": "@alavida/value-copywriting",
131
145
  "version": "1.0.0",
146
+ "agentpack": {
147
+ "skills": {
148
+ "value-copywriting": {
149
+ "path": "skills/value-copywriting/SKILL.md"
150
+ }
151
+ }
152
+ },
132
153
  "repository": {
133
154
  "type": "git",
134
155
  "url": "git+https://github.com/alavida-ai/knowledge-base.git"
@@ -1,6 +1,7 @@
1
1
  # Authored Metadata
2
2
 
3
3
  - `SKILL.md` owns `name`, `description`, `metadata.sources`, and `requires`
4
- - `package.json` owns distribution metadata such as package name, version, publish config, and repository
5
- - `skills validate` syncs managed dependencies from `requires` and refreshes `.agentpack/build-state.json`
6
-
4
+ - `package.json.agentpack.skills` owns the exported skill map and each exported skill path
5
+ - `package.json` owns package-level distribution metadata such as package name, version, publish config, and repository
6
+ - `requires` uses canonical ids like `@scope/package:skill-name`
7
+ - `skills validate` syncs managed cross-package dependencies from `requires` and refreshes `.agentpack/build-state.json`
@@ -3,7 +3,7 @@ name: getting-started-skillgraphs
3
3
  description: Use when starting from an empty repo or empty skillgraph and needing the first correct authoring loop, lifecycle framing, repo-root routing, and inspect/validate/dev command flow in agentpack.
4
4
  type: lifecycle
5
5
  library: agentpack
6
- library_version: "0.1.3"
6
+ library_version: "0.1.4"
7
7
  sources:
8
8
  - "alavida-ai/agentpack:docs/introduction.mdx"
9
9
  - "alavida-ai/agentpack:docs/commands.mdx"
@@ -46,7 +46,7 @@ agentpack skills dev domains/value/skills/copywriting
46
46
 
47
47
  ```bash
48
48
  cd consumer-repo
49
- agentpack skills install @alavida-ai/value-copywriting
49
+ agentpack skills install @alavida/value-copywriting
50
50
  agentpack skills env
51
51
  ```
52
52
 
@@ -77,7 +77,7 @@ Source: docs/introduction.mdx
77
77
  Wrong:
78
78
 
79
79
  ```bash
80
- agentpack skills install @alavida-ai/value-copywriting
80
+ agentpack skills install @alavida/value-copywriting
81
81
  ```
82
82
 
83
83
  Correct:
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  name: shipping-production-plugins-and-packages
3
- description: Use when turning maintained skills into deployable bundled plugins or publishable standalone packages with explicit dependency closure, hooks, MCP tools, and production checks in agentpack.
3
+ description: Use when turning maintained skills into deployable bundled plugins or publishable skill packages with explicit dependency closure, hooks, MCP tools, and production checks in agentpack.
4
4
  type: core
5
5
  library: agentpack
6
- library_version: "0.1.3"
6
+ library_version: "0.1.4"
7
7
  sources:
8
8
  - "alavida-ai/agentpack:docs/commands.mdx"
9
9
  - "alavida-ai/agentpack:docs/architecture.mdx"
@@ -26,13 +26,21 @@ agentpack plugin build plugins/website-dev
26
26
 
27
27
  ## Core Patterns
28
28
 
29
- ### Ship a standalone package for one reusable capability
29
+ ### Ship one package for one reusable skill module
30
30
 
31
31
  ```bash
32
32
  agentpack skills validate domains/value/skills/copywriting
33
33
  ```
34
34
 
35
- Use this when the capability stands on its own and does not need to ship bundled with hooks, MCP tools, or other skills.
35
+ Use this when one package should export one reusable skill module and does not need to ship bundled with hooks, MCP tools, or other runtime pieces.
36
+
37
+ ### Ship one package that exports several related skill modules
38
+
39
+ ```bash
40
+ agentpack skills validate domains/value/skills/pm-foundations
41
+ ```
42
+
43
+ Use this when several skills belong together as one package but still need to remain separate runtime modules through `package.json.agentpack.skills`.
36
44
 
37
45
  ### Bundle a production plugin when shipping several skills together
38
46
 
@@ -56,7 +64,7 @@ Wrong:
56
64
 
57
65
  ```yaml
58
66
  requires:
59
- - @alavida-ai/value-copywriting
67
+ - "@alavida/value-copywriting:value-copywriting"
60
68
  ```
61
69
 
62
70
  ```json
@@ -70,7 +78,7 @@ Correct:
70
78
  ```json
71
79
  {
72
80
  "devDependencies": {
73
- "@alavida-ai/value-copywriting": "^1.0.0"
81
+ "@alavida/value-copywriting": "^1.0.0"
74
82
  }
75
83
  }
76
84
  ```
@@ -110,11 +118,11 @@ Publish one packaged skill and assume hooks, MCP tools, and related skills ship
110
118
  Correct:
111
119
 
112
120
  ```text
113
- Use a standalone package for one reusable capability
121
+ Use a skill package for one or many reusable skill modules
114
122
  Use a bundled plugin when several skills, hooks, or MCP tools must ship together
115
123
  ```
116
124
 
117
- Packaged skills are reusable units; plugins are deployable runtime shells.
125
+ Skill packages are reusable distribution units; exported skills are runtime modules; plugins are deployable runtime shells.
118
126
 
119
127
  Source: README.md
120
128
 
@@ -0,0 +1,97 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { readUserConfig } from '../../infrastructure/fs/user-config-repository.js';
4
+ import { readUserCredentials } from '../../infrastructure/fs/user-credentials-repository.js';
5
+ import { getUserNpmrcPath, parseNpmrc, readUserNpmrc } from '../../infrastructure/fs/user-npmrc-repository.js';
6
+ import { resolveRegistryConfig } from '../../domain/auth/registry-resolution.js';
7
+ import { verifyAuth } from './verify-auth.js';
8
+
9
+ function findRepoNpmrc(cwd) {
10
+ let current = cwd;
11
+
12
+ while (true) {
13
+ const npmrcPath = join(current, '.npmrc');
14
+ if (existsSync(npmrcPath)) {
15
+ return {
16
+ path: npmrcPath,
17
+ config: parseNpmrc(readFileSync(npmrcPath, 'utf-8')),
18
+ };
19
+ }
20
+
21
+ const gitPath = join(current, '.git');
22
+ if (existsSync(gitPath)) break;
23
+
24
+ const parent = join(current, '..');
25
+ if (parent === current) break;
26
+ current = parent;
27
+ }
28
+
29
+ return {
30
+ path: null,
31
+ config: {},
32
+ };
33
+ }
34
+
35
+ export async function getAuthStatus({
36
+ cwd = process.cwd(),
37
+ env = process.env,
38
+ verify = false,
39
+ } = {}) {
40
+ const config = readUserConfig({ env });
41
+ const credentials = readUserCredentials({ env });
42
+ const userNpmrc = readUserNpmrc({ env });
43
+ const repoNpmrc = findRepoNpmrc(cwd);
44
+
45
+ const resolved = resolveRegistryConfig({
46
+ scope: config.scope,
47
+ defaults: {
48
+ registry: config.registry,
49
+ verificationPackage: config.verificationPackage,
50
+ },
51
+ userNpmrc,
52
+ repoNpmrc: repoNpmrc.config,
53
+ });
54
+
55
+ const userNpmrcPath = getUserNpmrcPath({ env });
56
+ const requiredRegistryKey = `${config.scope}:registry`;
57
+ const requiredTokenKey = resolved.registry
58
+ ? `//${new URL(resolved.registry).host}/:_authToken`
59
+ : null;
60
+
61
+ const npmWired = Boolean(
62
+ userNpmrc[requiredRegistryKey]
63
+ && requiredTokenKey
64
+ && userNpmrc[requiredTokenKey]
65
+ );
66
+
67
+ const result = {
68
+ provider: config.provider,
69
+ configured: Boolean(credentials?.token && npmWired),
70
+ scope: config.scope,
71
+ registry: resolved.registry,
72
+ storage: {
73
+ mode: credentials?.token ? 'file' : 'missing',
74
+ },
75
+ npmConfig: {
76
+ path: userNpmrcPath,
77
+ wired: npmWired,
78
+ source: resolved.source,
79
+ repoOverridePath: repoNpmrc.path,
80
+ },
81
+ verification: {
82
+ status: 'not_checked',
83
+ },
84
+ };
85
+
86
+ if (!verify) {
87
+ return result;
88
+ }
89
+
90
+ result.verification = await verifyAuth({
91
+ registry: resolved.registry,
92
+ authToken: credentials?.token || null,
93
+ verificationPackage: resolved.verificationPackage,
94
+ });
95
+
96
+ return result;
97
+ }
@@ -0,0 +1,110 @@
1
+ import readline from 'node:readline/promises';
2
+ import { stdin as input, stdout as output } from 'node:process';
3
+ import { readUserConfig, writeUserConfig } from '../../infrastructure/fs/user-config-repository.js';
4
+ import { writeUserCredentials } from '../../infrastructure/fs/user-credentials-repository.js';
5
+ import { writeManagedNpmrcEntries } from '../../infrastructure/fs/user-npmrc-repository.js';
6
+ import { openBrowser } from '../../infrastructure/runtime/open-browser.js';
7
+ import { verifyAuth } from './verify-auth.js';
8
+ import { AgentpackError, EXIT_CODES } from '../../utils/errors.js';
9
+
10
+ const GITHUB_TOKEN_URL = 'https://github.com/settings/tokens';
11
+
12
+ function buildVerificationFailure(verification) {
13
+ if (verification.status === 'invalid') {
14
+ return new AgentpackError('The GitHub personal access token was rejected by GitHub Packages', {
15
+ code: 'auth_verification_failed',
16
+ exitCode: EXIT_CODES.GENERAL,
17
+ });
18
+ }
19
+
20
+ if (verification.status === 'insufficient_permissions') {
21
+ return new AgentpackError('The GitHub personal access token does not have package read access', {
22
+ code: 'auth_verification_failed',
23
+ exitCode: EXIT_CODES.GENERAL,
24
+ });
25
+ }
26
+
27
+ if (verification.status === 'unreachable') {
28
+ return new AgentpackError('GitHub Packages could not be reached during verification', {
29
+ code: 'auth_verification_failed',
30
+ exitCode: EXIT_CODES.GENERAL,
31
+ });
32
+ }
33
+
34
+ if (verification.status === 'not_configured') {
35
+ return new AgentpackError('Authentication verification is not configured for this machine', {
36
+ code: 'auth_verification_not_configured',
37
+ exitCode: EXIT_CODES.GENERAL,
38
+ });
39
+ }
40
+
41
+ return new AgentpackError('The saved credential was rejected by the configured registry', {
42
+ code: 'auth_verification_failed',
43
+ exitCode: EXIT_CODES.GENERAL,
44
+ });
45
+ }
46
+
47
+ export async function login({
48
+ env = process.env,
49
+ scope = null,
50
+ registry = null,
51
+ verificationPackage = null,
52
+ } = {}) {
53
+ const current = readUserConfig({ env });
54
+ const nextConfig = {
55
+ ...current,
56
+ scope: scope || current.scope,
57
+ registry: registry || current.registry,
58
+ verificationPackage: verificationPackage || current.verificationPackage,
59
+ };
60
+
61
+ openBrowser(GITHUB_TOKEN_URL);
62
+ output.write(`Configuring GitHub Packages auth for ${nextConfig.scope}`);
63
+ output.write('Use a GitHub personal access token with package read access.');
64
+
65
+ const rl = readline.createInterface({ input, output });
66
+ try {
67
+ const token = (await rl.question('Token: ')).trim();
68
+ if (!token) {
69
+ throw new AgentpackError('A GitHub credential is required to continue', {
70
+ code: 'auth_token_missing',
71
+ exitCode: EXIT_CODES.GENERAL,
72
+ });
73
+ }
74
+
75
+ const verification = await verifyAuth({
76
+ registry: nextConfig.registry,
77
+ authToken: token,
78
+ verificationPackage: nextConfig.verificationPackage,
79
+ });
80
+
81
+ if (verification.status !== 'valid') {
82
+ throw buildVerificationFailure(verification);
83
+ }
84
+
85
+ const managedEntries = {
86
+ [`${nextConfig.scope}:registry`]: nextConfig.registry,
87
+ [`//${new URL(nextConfig.registry).host}/:_authToken`]: token,
88
+ };
89
+
90
+ writeManagedNpmrcEntries({ entries: managedEntries, env });
91
+ writeUserCredentials({ token }, { env });
92
+ writeUserConfig({
93
+ ...nextConfig,
94
+ managedNpmKeys: Object.keys(managedEntries),
95
+ }, { env });
96
+
97
+ return {
98
+ configured: true,
99
+ provider: nextConfig.provider,
100
+ scope: nextConfig.scope,
101
+ registry: nextConfig.registry,
102
+ verificationPackage: nextConfig.verificationPackage,
103
+ storage: {
104
+ mode: 'file',
105
+ },
106
+ };
107
+ } finally {
108
+ rl.close();
109
+ }
110
+ }
@@ -0,0 +1,16 @@
1
+ import { deleteUserCredentials } from '../../infrastructure/fs/user-credentials-repository.js';
2
+ import { removeManagedNpmrcEntries } from '../../infrastructure/fs/user-npmrc-repository.js';
3
+ import { readUserConfig } from '../../infrastructure/fs/user-config-repository.js';
4
+
5
+ export function logout({ env = process.env } = {}) {
6
+ const config = readUserConfig({ env });
7
+ const keys = config.managedNpmKeys || [];
8
+
9
+ deleteUserCredentials({ env });
10
+ removeManagedNpmrcEntries({ keys, env });
11
+
12
+ return {
13
+ removedCredentials: true,
14
+ removedNpmKeys: keys.length,
15
+ };
16
+ }
@@ -0,0 +1,37 @@
1
+ export async function verifyAuth({
2
+ registry,
3
+ authToken,
4
+ verificationPackage,
5
+ } = {}) {
6
+ if (!registry || !authToken || !verificationPackage) {
7
+ return { status: 'not_configured' };
8
+ }
9
+
10
+ const url = `${registry.replace(/\/+$/, '')}/${encodeURIComponent(verificationPackage)}`;
11
+
12
+ let response;
13
+ try {
14
+ response = await fetch(url, {
15
+ headers: {
16
+ accept: 'application/json',
17
+ authorization: `Bearer ${authToken}`,
18
+ },
19
+ });
20
+ } catch {
21
+ return { status: 'unreachable' };
22
+ }
23
+
24
+ if (response.ok) {
25
+ return { status: 'valid' };
26
+ }
27
+
28
+ if (response.status === 401) {
29
+ return { status: 'invalid' };
30
+ }
31
+
32
+ if (response.status === 403) {
33
+ return { status: 'insufficient_permissions' };
34
+ }
35
+
36
+ return { status: 'unreachable' };
37
+ }
package/src/cli.js CHANGED
@@ -2,6 +2,7 @@ import { Command } from 'commander';
2
2
  import { createRequire } from 'node:module';
3
3
  import { formatError, AgentpackError, EXIT_CODES } from './utils/errors.js';
4
4
  import { output } from './utils/output.js';
5
+ import { authCommand } from './commands/auth.js';
5
6
  import { skillsCommand } from './commands/skills.js';
6
7
  import { pluginCommand } from './commands/plugin.js';
7
8
 
@@ -21,6 +22,7 @@ export function createProgram() {
21
22
  .option('--workbench <path>', 'Override workbench context (name or path)');
22
23
 
23
24
  program.addCommand(skillsCommand());
25
+ program.addCommand(authCommand());
24
26
  program.addCommand(pluginCommand());
25
27
 
26
28
  program.addHelpText('after', `