@stigg/terminal 0.0.1-alpha → 0.1.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.
Files changed (148) hide show
  1. package/LICENSE +18 -12
  2. package/README.md +2 -2
  3. package/dist/api/graphql-client.js +1 -1
  4. package/dist/api/operations.js +1 -4
  5. package/dist/auth/callback-server.js +1 -2
  6. package/dist/bin.js +0 -0
  7. package/dist/cli.js +2 -7
  8. package/dist/headless/init-phase2.js +1 -1
  9. package/dist/headless/setup.js +2 -2
  10. package/dist/launch/agent.js +1 -3
  11. package/dist/mcp/clients/claude-code.js +1 -1
  12. package/dist/mcp/clients/codex.js +1 -1
  13. package/dist/mcp/writer.js +1 -3
  14. package/dist/ui/intro/LogoView.js +2 -7
  15. package/dist/ui/tui/App.js +1 -1
  16. package/dist/ui/tui/hooks/useKeyBindings.js +1 -1
  17. package/dist/ui/tui/hooks/useStdoutDimensions.js +1 -4
  18. package/dist/ui/tui/primitives/PickerMenu.js +3 -5
  19. package/dist/ui/tui/screens/EnvScreen.js +2 -2
  20. package/dist/ui/tui/steps/AccountStep.js +1 -4
  21. package/dist/ui/tui/steps/ApiKeyStep.js +1 -1
  22. package/dist/ui/tui/steps/ClientsStep.js +1 -3
  23. package/dist/ui/tui/steps/SummaryStep.js +1 -3
  24. package/package.json +9 -10
  25. package/dist/api/client.d.ts +0 -6
  26. package/dist/api/format-key.d.ts +0 -7
  27. package/dist/api/graphql-client.d.ts +0 -5
  28. package/dist/api/operations.d.ts +0 -65
  29. package/dist/api/types.d.ts +0 -18
  30. package/dist/auth/callback-server.d.ts +0 -14
  31. package/dist/auth/config.d.ts +0 -2
  32. package/dist/auth/oauth.d.ts +0 -17
  33. package/dist/auth/storage.d.ts +0 -6
  34. package/dist/bin.d.ts +0 -2
  35. package/dist/cli.d.ts +0 -1
  36. package/dist/commands/dash.d.ts +0 -1
  37. package/dist/commands/debug.d.ts +0 -1
  38. package/dist/commands/debug.js +0 -53
  39. package/dist/commands/env.d.ts +0 -1
  40. package/dist/commands/init.d.ts +0 -13
  41. package/dist/commands/mcp.d.ts +0 -7
  42. package/dist/commands/skills.d.ts +0 -6
  43. package/dist/headless/host-agent.d.ts +0 -19
  44. package/dist/headless/init-phase1.d.ts +0 -9
  45. package/dist/headless/init-phase2.d.ts +0 -36
  46. package/dist/headless/next-step-prompt.d.ts +0 -7
  47. package/dist/headless/options.d.ts +0 -30
  48. package/dist/headless/reporter.d.ts +0 -16
  49. package/dist/headless/setup.d.ts +0 -29
  50. package/dist/launch/agent.d.ts +0 -55
  51. package/dist/mcp/clients/base.d.ts +0 -49
  52. package/dist/mcp/clients/claude-code.d.ts +0 -22
  53. package/dist/mcp/clients/claude-desktop.d.ts +0 -9
  54. package/dist/mcp/clients/codex.d.ts +0 -13
  55. package/dist/mcp/clients/cursor.d.ts +0 -9
  56. package/dist/mcp/clients/index.d.ts +0 -7
  57. package/dist/mcp/clients/mcp-remote.d.ts +0 -11
  58. package/dist/mcp/clients/vscode.d.ts +0 -17
  59. package/dist/mcp/clients.d.ts +0 -4
  60. package/dist/mcp/clients.js +0 -50
  61. package/dist/mcp/config-merge.d.ts +0 -9
  62. package/dist/mcp/writer.d.ts +0 -6
  63. package/dist/setup/storage.d.ts +0 -21
  64. package/dist/skills/install.d.ts +0 -19
  65. package/dist/types.d.ts +0 -35
  66. package/dist/ui/components/Card.d.ts +0 -11
  67. package/dist/ui/components/Card.js +0 -19
  68. package/dist/ui/components/ContextRow.d.ts +0 -11
  69. package/dist/ui/components/ContextRow.js +0 -8
  70. package/dist/ui/components/Footer.d.ts +0 -10
  71. package/dist/ui/components/Footer.js +0 -9
  72. package/dist/ui/components/Header.d.ts +0 -11
  73. package/dist/ui/components/Header.js +0 -6
  74. package/dist/ui/components/JsonPreview.d.ts +0 -13
  75. package/dist/ui/components/JsonPreview.js +0 -25
  76. package/dist/ui/components/SectionTitle.d.ts +0 -6
  77. package/dist/ui/components/SectionTitle.js +0 -5
  78. package/dist/ui/hooks/useAsyncEffect.d.ts +0 -3
  79. package/dist/ui/hooks/useResize.d.ts +0 -4
  80. package/dist/ui/hooks/useResize.js +0 -20
  81. package/dist/ui/hud.d.ts +0 -15
  82. package/dist/ui/ink-theme.d.ts +0 -2
  83. package/dist/ui/ink-theme.js +0 -34
  84. package/dist/ui/intro/LogoView.d.ts +0 -12
  85. package/dist/ui/intro/MatrixIntro.d.ts +0 -6
  86. package/dist/ui/intro/MatrixIntro.js +0 -80
  87. package/dist/ui/intro/logo.d.ts +0 -6
  88. package/dist/ui/messages.d.ts +0 -5
  89. package/dist/ui/screens/DashScreen.d.ts +0 -6
  90. package/dist/ui/screens/DashScreen.js +0 -27
  91. package/dist/ui/screens/DebugScreen.d.ts +0 -6
  92. package/dist/ui/screens/DebugScreen.js +0 -39
  93. package/dist/ui/screens/InitScreen.d.ts +0 -6
  94. package/dist/ui/screens/InitScreen.js +0 -138
  95. package/dist/ui/screens/MenuScreen.d.ts +0 -7
  96. package/dist/ui/screens/MenuScreen.js +0 -38
  97. package/dist/ui/state.d.ts +0 -72
  98. package/dist/ui/steps/AccountStep.d.ts +0 -8
  99. package/dist/ui/steps/AccountStep.js +0 -42
  100. package/dist/ui/steps/ApiKeyStep.d.ts +0 -8
  101. package/dist/ui/steps/ApiKeyStep.js +0 -91
  102. package/dist/ui/steps/ClientsStep.d.ts +0 -10
  103. package/dist/ui/steps/ClientsStep.js +0 -69
  104. package/dist/ui/steps/CredentialKindStep.d.ts +0 -7
  105. package/dist/ui/steps/CredentialKindStep.js +0 -18
  106. package/dist/ui/steps/EnvironmentStep.d.ts +0 -8
  107. package/dist/ui/steps/EnvironmentStep.js +0 -37
  108. package/dist/ui/steps/LoginStep.d.ts +0 -7
  109. package/dist/ui/steps/LoginStep.js +0 -56
  110. package/dist/ui/steps/SkillsStep.d.ts +0 -7
  111. package/dist/ui/steps/SkillsStep.js +0 -7
  112. package/dist/ui/steps/SummaryStep.d.ts +0 -8
  113. package/dist/ui/steps/SummaryStep.js +0 -41
  114. package/dist/ui/steps/WritingStep.d.ts +0 -10
  115. package/dist/ui/steps/WritingStep.js +0 -96
  116. package/dist/ui/theme.d.ts +0 -53
  117. package/dist/ui/tui/App.d.ts +0 -10
  118. package/dist/ui/tui/components/ContextStrip.d.ts +0 -11
  119. package/dist/ui/tui/components/TitleBar.d.ts +0 -6
  120. package/dist/ui/tui/components/WizardChecklist.d.ts +0 -7
  121. package/dist/ui/tui/hooks/keyboard-hints-utils.d.ts +0 -26
  122. package/dist/ui/tui/hooks/useKeyBindings.d.ts +0 -14
  123. package/dist/ui/tui/hooks/useKeyboardHints.d.ts +0 -13
  124. package/dist/ui/tui/hooks/useStdoutDimensions.d.ts +0 -8
  125. package/dist/ui/tui/primitives/BlinkingLabel.d.ts +0 -19
  126. package/dist/ui/tui/primitives/ConfirmPrompt.d.ts +0 -16
  127. package/dist/ui/tui/primitives/KeyboardHintsBar.d.ts +0 -2
  128. package/dist/ui/tui/primitives/PickerMenu.d.ts +0 -38
  129. package/dist/ui/tui/primitives/PromptLabel.d.ts +0 -6
  130. package/dist/ui/tui/primitives/ScreenContainer.d.ts +0 -39
  131. package/dist/ui/tui/primitives/Spinner.d.ts +0 -7
  132. package/dist/ui/tui/screens/DashScreen.d.ts +0 -6
  133. package/dist/ui/tui/screens/DebugScreen.d.ts +0 -6
  134. package/dist/ui/tui/screens/DebugScreen.js +0 -48
  135. package/dist/ui/tui/screens/EnvScreen.d.ts +0 -6
  136. package/dist/ui/tui/screens/InitScreen.d.ts +0 -9
  137. package/dist/ui/tui/screens/MenuScreen.d.ts +0 -7
  138. package/dist/ui/tui/start-tui.d.ts +0 -11
  139. package/dist/ui/tui/steps/AccountStep.d.ts +0 -8
  140. package/dist/ui/tui/steps/ApiKeyStep.d.ts +0 -8
  141. package/dist/ui/tui/steps/ClientsStep.d.ts +0 -10
  142. package/dist/ui/tui/steps/CredentialKindStep.d.ts +0 -7
  143. package/dist/ui/tui/steps/CredentialKindStep.js +0 -18
  144. package/dist/ui/tui/steps/EnvironmentStep.d.ts +0 -8
  145. package/dist/ui/tui/steps/LoginStep.d.ts +0 -8
  146. package/dist/ui/tui/steps/SkillsStep.d.ts +0 -7
  147. package/dist/ui/tui/steps/SummaryStep.d.ts +0 -10
  148. package/dist/ui/tui/steps/WritingStep.d.ts +0 -10
package/LICENSE CHANGED
@@ -1,15 +1,21 @@
1
- ISC License
1
+ MIT License
2
2
 
3
3
  Copyright (c) 2026 Stigg
4
4
 
5
- Permission to use, copy, modify, and/or distribute this software for any
6
- purpose with or without fee is hereby granted, provided that the above
7
- copyright notice and this permission notice appear in all copies.
8
-
9
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  Desktop, Cursor, VS Code, Codex, …) to Stigg — authenticating you, writing the Stigg MCP server
7
7
  into each client's config, and installing the Stigg skills, all from one place.
8
8
 
9
- > ⚠️ **Alpha** (`0.0.1-alpha`) — under active development; expect breaking changes.
9
+ > ⚠️ **Early release** (`0.1.0`) — under active development; expect breaking changes.
10
10
 
11
11
  ## Requirements
12
12
 
@@ -44,4 +44,4 @@ Run `stiggt <command> --help` for the full set of flags on any command.
44
44
 
45
45
  ## License
46
46
 
47
- ISC
47
+ MIT
@@ -39,6 +39,6 @@ export async function gqlRequest(client, query, variables) {
39
39
  return await client.request(query, variables);
40
40
  }
41
41
  catch (err) {
42
- throw new Error(formatGqlError(err));
42
+ throw new Error(formatGqlError(err), { cause: err });
43
43
  }
44
44
  }
@@ -16,10 +16,7 @@ export const CURRENT_USER_QUERY = /* GraphQL */ `
16
16
  `;
17
17
  export const ENVIRONMENTS_QUERY = /* GraphQL */ `
18
18
  query StiggTerminalEnvironments {
19
- environments(
20
- filter: { permanentDeletionDate: { is: null } }
21
- paging: { first: 50 }
22
- ) {
19
+ environments(filter: { permanentDeletionDate: { is: null } }, paging: { first: 50 }) {
23
20
  edges {
24
21
  node {
25
22
  id
@@ -6,8 +6,7 @@ export async function startCallbackServer(options = {}) {
6
6
  resolveCallback = resolve;
7
7
  rejectCallback = reject;
8
8
  });
9
- let server;
10
- server = createServer((req, res) => {
9
+ const server = createServer((req, res) => {
11
10
  if (!req.url) {
12
11
  res.writeHead(400).end();
13
12
  return;
package/dist/bin.js CHANGED
File without changes
package/dist/cli.js CHANGED
@@ -48,9 +48,7 @@ export function cli(argv = process.argv) {
48
48
  .option('--all', 'target every detected client')
49
49
  .option('--json', 'JSON output')
50
50
  .action(mcpAddCommand);
51
- const skills = program
52
- .command('skills')
53
- .description('Manage Stigg skills install for AI clients');
51
+ const skills = program.command('skills').description('Manage Stigg skills install for AI clients');
54
52
  skills
55
53
  .command('add')
56
54
  .description('Install Stigg skills for one or more AI clients (non-interactive)')
@@ -59,10 +57,7 @@ export function cli(argv = process.argv) {
59
57
  .option('--json', 'JSON output')
60
58
  .action(skillsAddCommand);
61
59
  program.command('env').description('Switch the active Stigg environment').action(envCommand);
62
- program
63
- .command('dash')
64
- .description('Open the Stigg dashboard in your browser')
65
- .action(dashCommand);
60
+ program.command('dash').description('Open the Stigg dashboard in your browser').action(dashCommand);
66
61
  program.parseAsync(argv).catch((err) => {
67
62
  if (err instanceof ConfigParseError) {
68
63
  console.error(pc.red(`\n✗ ${messages.writes.abortMalformed(err.path)}`));
@@ -5,7 +5,7 @@ import { getClientById } from '../mcp/clients/index.js';
5
5
  import { saveSetup } from '../setup/storage.js';
6
6
  import { detectHostAgent } from './host-agent.js';
7
7
  import { nextStepPrompt, restartHint } from './next-step-prompt.js';
8
- import { HeadlessOptionsError, resolveClientSelectionForInit, } from './options.js';
8
+ import { HeadlessOptionsError, resolveClientSelectionForInit } from './options.js';
9
9
  import { createReporter, fmt } from './reporter.js';
10
10
  import { runHeadlessSetup } from './setup.js';
11
11
  export async function runInitPhase2(opts) {
@@ -1,5 +1,5 @@
1
- import { getAllClients, getClientById, getSupportedClients, } from '../mcp/clients/index.js';
2
- import { installStiggSkills, } from '../skills/install.js';
1
+ import { getAllClients, getClientById, getSupportedClients } from '../mcp/clients/index.js';
2
+ import { installStiggSkills } from '../skills/install.js';
3
3
  import { HeadlessOptionsError } from './options.js';
4
4
  async function resolveClients(selection, progress, result) {
5
5
  if (selection.kind === 'all') {
@@ -101,9 +101,7 @@ export function launchAgent(req) {
101
101
  if (!binary) {
102
102
  return Promise.reject(new Error(`${AGENT_NAMES[req.agentId]} CLI ("${AGENT_BINARIES[req.agentId]}") was not found on your PATH`));
103
103
  }
104
- const args = req.skipPermissions
105
- ? [AGENT_SKIP_PERMISSION_FLAGS[req.agentId], req.prompt]
106
- : [req.prompt];
104
+ const args = req.skipPermissions ? [AGENT_SKIP_PERMISSION_FLAGS[req.agentId], req.prompt] : [req.prompt];
107
105
  return new Promise((resolve, reject) => {
108
106
  const child = spawn(binary, args, { stdio: 'inherit', cwd: process.cwd() });
109
107
  child.on('error', reject);
@@ -2,7 +2,7 @@ import { execFileSync, execSync } from 'node:child_process';
2
2
  import { existsSync } from 'node:fs';
3
3
  import { homedir } from 'node:os';
4
4
  import { join } from 'node:path';
5
- import { errorMessage, McpClient, STIGG_MCP_URL, STIGG_SERVER_NAME, } from './base.js';
5
+ import { errorMessage, McpClient, STIGG_MCP_URL, STIGG_SERVER_NAME } from './base.js';
6
6
  let cachedBinary;
7
7
  /**
8
8
  * Locate the `claude` CLI binary using PostHog wizard's lookup order:
@@ -4,7 +4,7 @@ import { homedir } from 'node:os';
4
4
  import { dirname, join } from 'node:path';
5
5
  import TOML from '@iarna/toml';
6
6
  import { optionalEnv } from '../../auth/config.js';
7
- import { errorMessage, McpClient, prettifyPath, STIGG_SERVER_NAME, } from './base.js';
7
+ import { errorMessage, McpClient, prettifyPath, STIGG_SERVER_NAME } from './base.js';
8
8
  import { buildMcpRemoteEntry } from './mcp-remote.js';
9
9
  export class CodexMcpClient extends McpClient {
10
10
  id = 'codex';
@@ -29,9 +29,7 @@ export async function writeMcpEntry(path, propertyName, serverName, entry) {
29
29
  if (fileExisted && text.trim()) {
30
30
  parseStrict(text, path);
31
31
  }
32
- const existed = fileExisted
33
- ? readJsonPath(parseStrict(text, path), [propertyName, serverName]) !== undefined
34
- : false;
32
+ const existed = fileExisted ? readJsonPath(parseStrict(text, path), [propertyName, serverName]) !== undefined : false;
35
33
  let backedUpTo;
36
34
  if (existed) {
37
35
  backedUpTo = `${path}.bak.${Date.now()}`;
@@ -145,10 +145,7 @@ export function Logo({ containerWidth }) {
145
145
  p.col += p.speed;
146
146
  p.twinklePhase += p.twinkleSpeed;
147
147
  if (p.greenUntil <= tickNow && Math.random() < GREEN_FLASH_CHANCE_PER_FRAME) {
148
- p.greenUntil =
149
- tickNow +
150
- GREEN_FLASH_MIN_MS +
151
- Math.random() * (GREEN_FLASH_MAX_MS - GREEN_FLASH_MIN_MS);
148
+ p.greenUntil = tickNow + GREEN_FLASH_MIN_MS + Math.random() * (GREEN_FLASH_MAX_MS - GREEN_FLASH_MIN_MS);
152
149
  }
153
150
  if (p.col >= maxCol) {
154
151
  const next = spawnParticle(TAIL_ORIGIN_COL);
@@ -169,9 +166,7 @@ export function Logo({ containerWidth }) {
169
166
  }, [animate, containerWidth]);
170
167
  const now = Date.now();
171
168
  const gradientPhase = animate ? Math.floor(now / GRADIENT_TICK_MS) % GRADIENT_PALETTE.length : 0;
172
- const activeRange = animate && LETTER_RANGES.length > 0
173
- ? LETTER_RANGES[letterIndexRef.current % LETTER_RANGES.length]
174
- : null;
169
+ const activeRange = animate && LETTER_RANGES.length > 0 ? LETTER_RANGES[letterIndexRef.current % LETTER_RANGES.length] : null;
175
170
  const animProgress = activeRange != null ? Math.min(1, (now - startedAtRef.current) / LETTER_ANIMATION_MS) : 0;
176
171
  const renderedLines = [];
177
172
  for (let row = 0; row < LOGO_ROWS; row++) {
@@ -9,7 +9,7 @@ import { InitScreen } from './screens/InitScreen.js';
9
9
  import { MenuScreen } from './screens/MenuScreen.js';
10
10
  import { useKeyBindings } from './hooks/useKeyBindings.js';
11
11
  import { ScreenContainer } from './primitives/ScreenContainer.js';
12
- function AppInner({ initialScreen = 'menu', callbackPort, onLaunchAgent, }) {
12
+ function AppInner({ initialScreen = 'menu', callbackPort, onLaunchAgent }) {
13
13
  const [screen, setScreen] = useState(initialScreen);
14
14
  const { exit } = useApp();
15
15
  useKeyBindings('app', [
@@ -1,6 +1,6 @@
1
1
  import { useInput } from 'ink';
2
2
  import { useEffect, useMemo } from 'react';
3
- import { defaultPriorityFor, matchesKey, } from './keyboard-hints-utils.js';
3
+ import { defaultPriorityFor, matchesKey } from './keyboard-hints-utils.js';
4
4
  import { useKeyboardHintsContext } from './useKeyboardHints.js';
5
5
  /**
6
6
  * Declarative key bindings + automatic hint registration.
@@ -9,10 +9,7 @@ import { useEffect, useState } from 'react';
9
9
  */
10
10
  export function useStdoutDimensions() {
11
11
  const { stdout } = useStdout();
12
- const [size, setSize] = useState(() => [
13
- stdout?.columns ?? 80,
14
- stdout?.rows ?? 24,
15
- ]);
12
+ const [size, setSize] = useState(() => [stdout?.columns ?? 80, stdout?.rows ?? 24]);
16
13
  useEffect(() => {
17
14
  if (!stdout)
18
15
  return undefined;
@@ -14,9 +14,7 @@ function findInitialIndex(options, defaultValue) {
14
14
  export function PickerMenu(props) {
15
15
  const { id, message, options, centered, optionMarginBottom = 0, visibleCount } = props;
16
16
  const mode = props.mode ?? 'single';
17
- const [focused, setFocused] = useState(() => mode === 'single'
18
- ? findInitialIndex(options, props.defaultValue)
19
- : 0);
17
+ const [focused, setFocused] = useState(() => mode === 'single' ? findInitialIndex(options, props.defaultValue) : 0);
20
18
  const windowSize = visibleCount && visibleCount > 0 ? Math.min(visibleCount, options.length) : options.length;
21
19
  const [windowStart, setWindowStart] = useState(() => clampWindowStart(focused, windowSize, options.length));
22
20
  useEffect(() => {
@@ -137,7 +135,7 @@ export function PickerMenu(props) {
137
135
  const windowEnd = Math.min(options.length, windowStart + windowSize);
138
136
  const hiddenAbove = windowStart;
139
137
  const hiddenBelow = options.length - windowEnd;
140
- return (_jsxs(Box, { flexDirection: "column", alignItems: centered ? 'center' : undefined, children: [message && _jsx(PromptLabel, { children: message }), _jsxs(Box, { flexDirection: "column", marginTop: message ? 1 : 0, children: [hiddenAbove > 0 && (_jsx(Text, { dimColor: true, children: ` ▲ ${hiddenAbove} more above` })), options.slice(windowStart, windowEnd).map((opt, j) => {
138
+ return (_jsxs(Box, { flexDirection: "column", alignItems: centered ? 'center' : undefined, children: [message && _jsx(PromptLabel, { children: message }), _jsxs(Box, { flexDirection: "column", marginTop: message ? 1 : 0, children: [hiddenAbove > 0 && _jsx(Text, { dimColor: true, children: ` ▲ ${hiddenAbove} more above` }), options.slice(windowStart, windowEnd).map((opt, j) => {
141
139
  const i = windowStart + j;
142
140
  const isFocused = i === focused;
143
141
  const isChecked = mode === 'multi' && selected.has(opt.value);
@@ -152,7 +150,7 @@ export function PickerMenu(props) {
152
150
  const numberTag = numbered && i < 9 ? `[${i + 1}] ` : '';
153
151
  const fullLabel = `${numberTag}${opt.label}`;
154
152
  return (_jsxs(Box, { flexDirection: "column", marginBottom: optionMarginBottom, children: [_jsxs(Box, { children: [_jsx(Text, { color: isFocused && !isDisabled ? Colors.accent : undefined, dimColor: !isFocused || isDisabled, children: indicatorGlyph }), _jsx(Text, { children: " " }), _jsx(Text, { color: isFocused && !isDisabled ? Colors.accent : undefined, bold: isFocused && !isDisabled, dimColor: !isFocused || isDisabled, children: fullLabel }), opt.hint && _jsx(Text, { dimColor: true, children: ` ${opt.hint}` })] }), opt.description && (_jsx(Box, { paddingLeft: 4, children: _jsx(Text, { dimColor: true, wrap: "truncate-end", children: opt.description }) }))] }, `${id}-opt-${i}`));
155
- }), hiddenBelow > 0 && (_jsx(Text, { dimColor: true, children: ` ▼ ${hiddenBelow} more below` }))] })] }));
153
+ }), hiddenBelow > 0 && _jsx(Text, { dimColor: true, children: ` ▼ ${hiddenBelow} more below` })] })] }));
156
154
  }
157
155
  function clampWindowStart(start, size, total) {
158
156
  if (total === 0 || size === 0)
@@ -91,13 +91,13 @@ export function EnvScreen({ onDone }) {
91
91
  return (_jsxs(Box, { flexDirection: "column", children: [_jsx(PromptLabel, { children: "No active Stigg setup" }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Run ", _jsx(Text, { color: Colors.accent, children: "terminal init" }), " first to sign in and pick an environment."] }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "press enter to go back" }) })] }));
92
92
  }
93
93
  if (phase.kind === 'no-snapshot') {
94
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(PromptLabel, { children: "No environment snapshot" }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Your saved setup is from an older version of terminal. Run", ' ', _jsx(Text, { color: Colors.accent, children: "terminal init" }), " once to refresh the environment list."] }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "press enter to go back" }) })] }));
94
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(PromptLabel, { children: "No environment snapshot" }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Your saved setup is from an older version of terminal. Run ", _jsx(Text, { color: Colors.accent, children: "terminal init" }), ' ', "once to refresh the environment list."] }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "press enter to go back" }) })] }));
95
95
  }
96
96
  if (phase.kind === 'error') {
97
97
  return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: Colors.error, children: "\u2717 Could not switch environment" }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: phase.message }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "press enter to go back" }) })] }));
98
98
  }
99
99
  if (phase.kind === 'no-keys') {
100
- return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(PromptLabel, { children: ["No API keys in ", phase.env.name] }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Create an API key for this environment in the Stigg dashboard (settings \u2192 API keys), then come back and run ", _jsx(Text, { color: Colors.accent, children: "terminal env" }), " again."] }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "press enter to go back" }) })] }));
100
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(PromptLabel, { children: ["No API keys in ", phase.env.name] }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Create an API key for this environment in the Stigg dashboard (settings \u2192 API keys), then come back and run", ' ', _jsx(Text, { color: Colors.accent, children: "terminal env" }), " again."] }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "press enter to go back" }) })] }));
101
101
  }
102
102
  if (phase.kind === 'saved') {
103
103
  return (_jsxs(Box, { flexDirection: "column", children: [_jsx(PromptLabel, { children: "Environment switched" }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { children: ["Active environment is now ", _jsx(Text, { color: Colors.accent, children: phase.env.name }), "."] }) }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { children: ["Active key is now ", _jsx(Text, { color: Colors.accent, children: phase.key.name }), " (", formatApiKeyShort(phase.key), ")."] }) }), phase.writes.length > 0 ? (_jsx(Box, { flexDirection: "column", marginTop: 1, children: phase.writes.map((w, i) => (_jsxs(Text, { color: Colors.success, children: [' ✓ ', w.path, w.backedUpTo ? (_jsxs(Text, { dimColor: true, children: [' (backup: ', w.backedUpTo, ')'] })) : null] }, i))) })) : (_jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "No MCP entries needed an update." }) })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "press enter to go back" }) })] }));
@@ -18,10 +18,7 @@ export function AccountStep({ state, dispatch }) {
18
18
  message: err instanceof Error ? err.message : String(err),
19
19
  }));
20
20
  useEffect(() => {
21
- if (state.accounts &&
22
- state.accounts.length === 1 &&
23
- !state.account &&
24
- state.step === 'account') {
21
+ if (state.accounts && state.accounts.length === 1 && !state.account && state.step === 'account') {
25
22
  dispatch({ type: 'PICK_ACCOUNT', account: state.accounts[0] });
26
23
  }
27
24
  }, [state.accounts, state.account, state.step, dispatch]);
@@ -37,7 +37,7 @@ export function ApiKeyStep({ state, dispatch }) {
37
37
  return _jsx(Spinner, { label: `Loading API keys for ${state.environment?.name}…` });
38
38
  }
39
39
  if (state.apiKeys.length === 0) {
40
- return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(PromptLabel, { children: ["No API keys in ", state.environment?.name] }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Create an API key for this environment in the Stigg dashboard (Settings \u2192 API keys), then press ", _jsx(Text, { color: Colors.accent, children: "esc" }), " to back up and try again."] }) })] }));
40
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(PromptLabel, { children: ["No API keys in ", state.environment?.name] }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Create an API key for this environment in the Stigg dashboard (Settings \u2192 API keys), then press", ' ', _jsx(Text, { color: Colors.accent, children: "esc" }), " to back up and try again."] }) })] }));
41
41
  }
42
42
  const handleSelect = (value) => {
43
43
  const key = state.apiKeys?.find((k) => k.id === value);
@@ -22,9 +22,7 @@ export function ClientsStep({ state, dispatch, clients }) {
22
22
  message: err instanceof Error ? err.message : String(err),
23
23
  }));
24
24
  const initial = state.selectedClients ??
25
- (state.detectedClients && state.detectedClients.length > 0
26
- ? state.detectedClients
27
- : ['claude-code']);
25
+ (state.detectedClients && state.detectedClients.length > 0 ? state.detectedClients : ['claude-code']);
28
26
  useKeyBindings('clients-skip', [
29
27
  {
30
28
  match: 's',
@@ -60,9 +60,7 @@ export function SummaryStep({ state, onDone, onLaunch }) {
60
60
  const showFallback = detection !== null && !canLaunch;
61
61
  // Fallback bindings — only active when there's no launchable agent and we
62
62
  // fall back to the static hints. When the picker is up it owns the keys.
63
- const fallbackBindings = [
64
- { match: KeyMatch.Return, label: 'enter', action: 'menu', handler: onDone },
65
- ];
63
+ const fallbackBindings = [{ match: KeyMatch.Return, label: 'enter', action: 'menu', handler: onDone }];
66
64
  if (env) {
67
65
  fallbackBindings.push({
68
66
  match: 'c',
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@stigg/terminal",
3
- "version": "0.0.1-alpha",
3
+ "version": "0.1.0",
4
4
  "type": "module",
5
5
  "description": "Stigg terminal — interactive setup TUI for AI coding assistants",
6
- "license": "ISC",
6
+ "license": "MIT",
7
7
  "author": "Stigg",
8
8
  "homepage": "https://stigg.io",
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "git+https://github.com/stiggio/stigg-lab.git",
12
- "directory": "projects/terminal"
11
+ "url": "https://github.com/stiggio/stigg-sdk.git",
12
+ "directory": "packages/terminal"
13
13
  },
14
14
  "bugs": {
15
- "url": "https://github.com/stiggio/stigg-lab/issues"
15
+ "url": "https://github.com/stiggio/stigg-sdk/issues"
16
16
  },
17
17
  "keywords": [
18
18
  "stigg",
@@ -36,12 +36,11 @@
36
36
  "dist"
37
37
  ],
38
38
  "scripts": {
39
- "build": "tsc",
40
- "prepublishOnly": "tsc",
41
- "dev": "tsx src/bin.ts",
39
+ "build": "yarn run -T tsc -p tsconfig.build.json",
40
+ "dev": "yarn run -T tsx src/bin.ts",
42
41
  "start": "node dist/bin.js",
43
- "lint": "eslint src/",
44
- "test": "jest --runInBand --forceExit"
42
+ "lint": "yarn run -T eslint src",
43
+ "test": "yarn run -T jest --runInBand --forceExit"
45
44
  },
46
45
  "dependencies": {
47
46
  "@iarna/toml": "^3.0.0",
@@ -1,6 +0,0 @@
1
- import type { Account } from '../types.js';
2
- import type { ApiKey, CreateScopedKeyOptions, Environment } from './types.js';
3
- export declare function listAccounts(accessToken: string): Promise<Account[]>;
4
- export declare function listEnvironments(accessToken: string, accountId: string): Promise<Environment[]>;
5
- export declare function listApiKeys(accessToken: string, accountId: string, envId: string): Promise<ApiKey[]>;
6
- export declare function createScopedApiKey(accessToken: string, accountId: string, envId: string, opts?: CreateScopedKeyOptions): Promise<string>;
@@ -1,7 +0,0 @@
1
- import type { ApiKey } from '../types.js';
2
- /**
3
- * Render a key's identity for UI display: first 8 chars of the secret +
4
- * `…` + last 4. Falls back to `…lastFour` when the secret value isn't
5
- * loaded (partial responses).
6
- */
7
- export declare function formatApiKeyShort(key: Pick<ApiKey, 'value' | 'lastFour'>): string;
@@ -1,5 +0,0 @@
1
- import { GraphQLClient } from 'graphql-request';
2
- export declare function graphqlEndpoint(): string;
3
- export declare function getGqlClient(accessToken: string, accountId?: string): GraphQLClient;
4
- export declare function formatGqlError(err: unknown): string;
5
- export declare function gqlRequest<T>(client: GraphQLClient, query: string, variables?: Record<string, unknown>): Promise<T>;
@@ -1,65 +0,0 @@
1
- export declare const CURRENT_USER_QUERY = "\n query StiggTerminalCurrentUser {\n currentUser {\n id\n email\n name\n memberships {\n id\n account {\n id\n displayName\n }\n }\n }\n }\n";
2
- export declare const ENVIRONMENTS_QUERY = "\n query StiggTerminalEnvironments {\n environments(\n filter: { permanentDeletionDate: { is: null } }\n paging: { first: 50 }\n ) {\n edges {\n node {\n id\n slug\n displayName\n type\n color\n }\n }\n }\n }\n";
3
- export declare const API_KEYS_QUERY = "\n query StiggTerminalApiKeys($envId: UUID!) {\n apiKeys(input: { environmentId: $envId, keyTypes: [SERVER, SCOPED], paging: { first: 50 } }) {\n edges {\n node {\n id\n displayName\n token\n keyType\n createdAt\n }\n }\n }\n }\n";
4
- export declare const CREATE_SCOPED_API_KEY_MUTATION = "\n mutation StiggTerminalCreateScopedApiKey($input: CreateScopedApiKeyInput!) {\n createScopedApiKey(input: $input) {\n id\n displayName\n token\n createdAt\n }\n }\n";
5
- export interface CurrentUserResult {
6
- currentUser: {
7
- id: string;
8
- email: string | null;
9
- name: string | null;
10
- memberships: Array<{
11
- id: string;
12
- account: {
13
- id: string;
14
- displayName: string;
15
- };
16
- }>;
17
- };
18
- }
19
- export interface EnvironmentsResult {
20
- environments: {
21
- edges: Array<{
22
- node: {
23
- id: string;
24
- slug: string;
25
- displayName: string;
26
- type: string;
27
- color: string | null;
28
- };
29
- }>;
30
- };
31
- }
32
- export interface ApiKeysResult {
33
- apiKeys: {
34
- edges: Array<{
35
- node: {
36
- id: string;
37
- displayName: string;
38
- token: string;
39
- keyType: string;
40
- createdAt: string;
41
- };
42
- }>;
43
- };
44
- }
45
- export interface CreateScopedApiKeyResult {
46
- createScopedApiKey: {
47
- id: string;
48
- displayName: string;
49
- token: string;
50
- createdAt: string;
51
- };
52
- }
53
- export type ApiKeyScopeAction = 'READ' | 'WRITE';
54
- export type ApiKeyScopeResource = 'API_KEY' | 'COUPON' | 'CUSTOMER' | 'ENVIRONMENT' | 'EVENT_QUEUE' | 'SUBSCRIPTION';
55
- export interface ApiKeyScopeInput {
56
- action: ApiKeyScopeAction;
57
- resource: ApiKeyScopeResource;
58
- }
59
- export interface CreateScopedApiKeyInput {
60
- description?: string;
61
- displayName: string;
62
- environmentId: string;
63
- scopes: ApiKeyScopeInput[];
64
- }
65
- export declare function fullScopeGrid(): ApiKeyScopeInput[];
@@ -1,18 +0,0 @@
1
- export interface Environment {
2
- id: string;
3
- name: string;
4
- slug?: string;
5
- }
6
- export interface CreateScopedKeyOptions {
7
- name?: string;
8
- scopes?: 'godmode' | string;
9
- }
10
- export interface ApiKey {
11
- id: string;
12
- name: string;
13
- lastFour: string;
14
- scopes: string[];
15
- keyType: string;
16
- createdAt: string;
17
- value?: string;
18
- }
@@ -1,14 +0,0 @@
1
- export interface CallbackServer {
2
- port: number;
3
- awaitCallback(): Promise<URL>;
4
- close(): void;
5
- }
6
- export interface StartCallbackServerOptions {
7
- /**
8
- * Loopback port to bind to. When omitted (or 0), the OS picks a free port.
9
- * Production runs always pass a fixed port so a single
10
- * `http://127.0.0.1:<port>/callback` can be whitelisted in the Auth0 app.
11
- */
12
- port?: number;
13
- }
14
- export declare function startCallbackServer(options?: StartCallbackServerOptions): Promise<CallbackServer>;
@@ -1,2 +0,0 @@
1
- export declare function loadEnv(): void;
2
- export declare function optionalEnv(name: string): string | undefined;
@@ -1,17 +0,0 @@
1
- export interface AuthSession {
2
- access_token: string;
3
- refresh_token?: string;
4
- id_token: string;
5
- expires_at: number;
6
- email: string;
7
- sub: string;
8
- scope?: string;
9
- }
10
- export interface AuthenticateOptions {
11
- onAuthUrlReady?: (url: string, port: number) => void;
12
- timeoutMs?: number;
13
- /** Fixed loopback port for the OAuth callback. Takes precedence over
14
- * `STIGG_CALLBACK_PORT`, which in turn overrides the built-in default. */
15
- port?: number;
16
- }
17
- export declare function authenticate(opts?: AuthenticateOptions): Promise<AuthSession>;
@@ -1,6 +0,0 @@
1
- import type { AuthSession } from './oauth.js';
2
- export declare function configDir(): string;
3
- export declare function credentialsPath(): string;
4
- export declare function saveSession(session: AuthSession): Promise<string>;
5
- export declare function loadSession(): Promise<AuthSession | null>;
6
- export declare function clearSession(): Promise<void>;
package/dist/bin.d.ts DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
package/dist/cli.d.ts DELETED
@@ -1 +0,0 @@
1
- export declare function cli(argv?: string[]): void;
@@ -1 +0,0 @@
1
- export declare function dashCommand(): Promise<void>;
@@ -1 +0,0 @@
1
- export declare function debugCommand(): Promise<void>;
@@ -1,53 +0,0 @@
1
- import pc from "picocolors";
2
- import { runHud } from "../ui/hud.js";
3
- const SAMPLE_LOGS = [
4
- {
5
- time: "16:42:13.221",
6
- level: "INFO",
7
- source: "feature.access",
8
- message: "customer=acme_corp has_access=true plan=growth feature=ai_credits",
9
- },
10
- {
11
- time: "16:42:14.034",
12
- level: "INFO",
13
- source: "usage.report",
14
- message: "customer=acme_corp feature=api_calls value=1 source=mcp",
15
- },
16
- {
17
- time: "16:42:18.512",
18
- level: "WARN",
19
- source: "entitlement.exceeded",
20
- message: "customer=acme_corp feature=api_calls usage=1001 limit=1000 reset_at=2026-07-01",
21
- },
22
- {
23
- time: "16:42:21.118",
24
- level: "INFO",
25
- source: "subscription.updated",
26
- message: "customer=acme_corp from=growth to=growth_v2 status=active",
27
- },
28
- ];
29
- const LEVEL_COLOR = {
30
- INFO: pc.green,
31
- WARN: pc.yellow,
32
- ERROR: pc.red,
33
- };
34
- export async function debugCommand() {
35
- if (process.stdin.isTTY) {
36
- await runHud({ initialScreen: "debug" });
37
- return;
38
- }
39
- // Non-TTY fallback (CI / pipe) — plain console output.
40
- console.log();
41
- console.log(pc.greenBright(pc.bold(" stigg · terminal · debug")));
42
- console.log(pc.dim(" ──────────────────────────"));
43
- console.log();
44
- console.log(pc.dim(" Streaming audit + usage logs (placeholder, sample output)…"));
45
- console.log();
46
- for (const log of SAMPLE_LOGS) {
47
- const colorFn = LEVEL_COLOR[log.level];
48
- console.log(` ${pc.dim(log.time)} ${colorFn(log.level.padEnd(5))} ${pc.cyan(log.source.padEnd(22))} ${log.message}`);
49
- }
50
- console.log();
51
- console.log(pc.dim(" (placeholder — the real command will live-tail audit + usage events for the active env, with `--since`, `--follow`, and `--filter` flags.)"));
52
- console.log();
53
- }
@@ -1 +0,0 @@
1
- export declare function envCommand(): Promise<void>;
@@ -1,13 +0,0 @@
1
- export interface InitOptions {
2
- headless?: boolean;
3
- forceLogin?: boolean;
4
- callbackPort?: string;
5
- accountId?: string;
6
- environmentId?: string;
7
- apiKeyId?: string;
8
- client?: string[];
9
- all?: boolean;
10
- skills?: boolean;
11
- json?: boolean;
12
- }
13
- export declare function initCommand(opts?: InitOptions): Promise<void>;
@@ -1,7 +0,0 @@
1
- export interface McpAddOptions {
2
- apiKey?: string;
3
- client?: string[];
4
- all?: boolean;
5
- json?: boolean;
6
- }
7
- export declare function mcpAddCommand(opts?: McpAddOptions): Promise<void>;