Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
8482397
wip
johnyeocx Oct 3, 2025
824ab43
wip
johnyeocx Oct 3, 2025
031c96a
wip
johnyeocx Oct 3, 2025
2e21416
fix: typegen
johnyeocx Oct 9, 2025
0954a8d
docs: ✏️ js docs for hooks
SirTenzin Oct 10, 2025
d5fbcd9
chore: 🤖 delete unecessary stuff
SirTenzin Oct 13, 2025
71703ac
chore: 🤖 remove shcmea
SirTenzin Oct 13, 2025
fd5437a
chore: 🤖 pnpm
SirTenzin Oct 13, 2025
6d3849f
feat: 🎸 convex auto typegen
SirTenzin Oct 13, 2025
731b7ca
feat: 🎸 cli
SirTenzin Oct 23, 2025
ec43223
feat: 🎸 push
SirTenzin Oct 23, 2025
6a519d7
feat: 🎸 idk
SirTenzin Oct 23, 2025
47d25c8
feat: 🎸 stuff
SirTenzin Oct 24, 2025
13a17e5
working on v2 autumn
johnyeocx Nov 13, 2025
f9a1885
v2 api
johnyeocx Nov 13, 2025
dd7f199
feat: 🎸 sync pkg version
SirTenzin Jan 5, 2026
884c837
Merge branch 'main' into feat/sdk-gen-atmn-plan-api
SirTenzin Jan 12, 2026
53e657c
feat: 🎸 tests, new sdk, etc
SirTenzin Jan 12, 2026
0a32968
feat: 🎸 atmn v2
SirTenzin Jan 13, 2026
e9bdf49
feat: 🎸 oauht proto v1
SirTenzin Jan 14, 2026
2b4fb1b
refactor: 💡 move to artic for oauth
SirTenzin Jan 14, 2026
2556e6b
feat: 🎸 old cli stuff
SirTenzin Jan 15, 2026
9e78161
feat: 🎸 everything in init flow is completed
SirTenzin Jan 15, 2026
ccfb396
feat: 🎸 misc changes
SirTenzin Jan 15, 2026
7821cdc
feat: 🎸 typegen ready for atmn v2
SirTenzin Jan 15, 2026
d6d9dd7
feat: 🎸 headless init
SirTenzin Jan 15, 2026
62a4482
feat: 🎸 customers commmand + push headless
SirTenzin Jan 19, 2026
2d0fa9a
chore: 🤖 cleanup old cmds
SirTenzin Jan 19, 2026
baa6bb1
feat: 🎸 final customers command
SirTenzin Jan 19, 2026
06a4f76
feat: 🎸 customer stuff
SirTenzin Jan 19, 2026
6a47dee
feat: 🎸 sync pkg version
SirTenzin Jan 19, 2026
daa5588
fix: restore deleted package/ files from main
SirTenzin Jan 19, 2026
f546e27
fix: 🐛 autumn-js
SirTenzin Jan 19, 2026
4cb8fed
feat: 🎸 dev on atmn auth
SirTenzin Jan 20, 2026
c475808
feat: 🎸 idk whats going on but fixed it
SirTenzin Jan 20, 2026
9d1e6da
feat: 🎸 next-gen autumn sdk
SirTenzin Jan 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[submodule "ts-sdk"]
path = ts-sdk
url = https://github.com/useautumn/ts-sdk
branch = next
3 changes: 2 additions & 1 deletion atmn/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
dist
.env
.env
test/.env.test
202 changes: 202 additions & 0 deletions atmn/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
# ATMN CLI - Code Conventions

## Directory Structure

The CLI has two source directories:

- **`source/`** - Legacy code (commands, core logic, compose builders)
- **`src/`** - New code following improved architecture

New features should be added to `src/`. Existing features in `source/` will be migrated incrementally.

```
atmn/
├── source/ # Legacy code
│ ├── cli.ts # Main entry point
│ ├── constants.ts # BACKEND_URL, FRONTEND_URL, DEFAULT_CONFIG
│ ├── index.ts # Package exports
│ ├── commands/ # CLI commands (pull, push, nuke, init)
│ ├── core/ # Business logic, API requests, utilities
│ └── compose/ # DSL builders for plans/features
├── src/ # New architecture
│ ├── commands/ # Command modules (each command in its own folder)
│ │ └── auth/ # Auth command
│ │ ├── command.ts # Main command export
│ │ ├── oauth.ts # OAuth flow logic
│ │ └── constants.ts # Command-specific constants
│ └── views/ # UI templates
│ └── html/ # HTML templates for browser callbacks
│ └── oauth-callback.ts
├── test/ # Tests
└── dist/ # Build output
```

## Architecture Conventions

### Commands (`src/commands/<name>/`)

Each command should have its own folder with:
- `command.ts` - The main command function (default export)
- `constants.ts` - Command-specific constants
- Additional files for supporting logic (e.g., `oauth.ts` for auth)

### Views (`src/views/`)

UI templates organized by type:
- `html/` - HTML templates (for browser callbacks, etc.)
- `react/` - React/Ink components (future)

### Shared Utilities

Currently in `source/core/utils.ts`. These will be migrated to `src/utils/` as needed:
- `env.ts` - Environment variable helpers (`readFromEnv`, `storeToEnv`)
- `spinner.ts` - CLI spinner (`initSpinner`)
- `string.ts` - String utilities

## Import Conventions

- Use `.js` extensions in imports (required for ESM)
- Import shared constants from `source/constants.js` (until migrated)
- Import utilities from `source/core/utils.js` (until migrated)

## OAuth Flow

The auth command uses OAuth 2.1 PKCE:
1. Local HTTP server starts on port `31448` (or next available up to `31452`)
2. Browser opens to backend authorize URL with PKCE challenge
3. User authenticates and selects organization
4. Callback received with authorization code
5. Code exchanged for access token
6. Access token used to create API keys via `/cli/api-keys` endpoint
7. Keys saved to `.env` file

Key constants:
- `CLI_CLIENT_ID`: `qncNuaPFAEBwzCypjFopNCGPHQDqkchp`
- `OAUTH_PORTS`: `31448-31452` (5 ports, tries each in sequence if previous is in use)

## React Component Conventions (`src/views/react/`)

When React files grow large, use folder-based decomposition:

1. **Create a folder with the component's name** - Replace `Component.tsx` with `Component/` folder
2. **Move parent into folder** - Place main component in `Component/Component.tsx`
3. **Extract children as siblings** - Create separate files for sub-components (e.g., `Component/SubComponent.tsx`)
4. **Apply recursively** - If children grow large, repeat the pattern for them
5. **Extract shared components** - Move frequently reused components to `react/components/`

**Example:**
```
react/
├── InitFlow.tsx # Original file (300+ lines)
# After decomposition:
├── init/
│ ├── InitFlow.tsx # Main orchestrator
│ └── steps/
│ ├── AuthStep.tsx # Step 1
│ ├── StripeStep.tsx # Step 2
│ └── ConfigStep.tsx # Step 3
└── components/ # Shared across multiple views
├── StepHeader.tsx
├── StatusLine.tsx
└── SelectMenu.tsx
```

**Useful Ink Components:**
- `ink-select-input` - Interactive select menus with arrow key navigation
- `ink-confirm-input` - Yes/No confirmation prompts
- `ink-spinner` - Loading spinners
- `ink-text-input` - Text input fields

## Build

```bash
npm run build # Build with tsup
npm run dev # Watch mode
npm run test # Run tests
```

Entry points are in `source/` but tsup follows imports to include `src/` files.

## Code Separation Rules

### .tsx Files (Components)
- **ONLY rendering logic** - No API calls, no business logic, no data transformation
- Import and use custom hooks for all data/state management
- No `useEffect` + `async/await` patterns
- No JSON boilerplate or large data constants

### .ts Files (Logic)
- All business logic, API calls, data transformation
- Custom hooks (`useX`) for stateful logic
- Utility functions for pure transformations
- Constants and configuration data

### Data Fetching
- **Always use TanStack Query for queries** - No `useEffect` + `async/await` for data fetching
- Create reusable hooks: `useOrganization`, `usePull`, etc.
- **Use TanStack Query for**: Data that should be cached/refetched (org info, lists, etc.)
- **Use useState + useEffect for**: One-time operations/mutations (pull, push, nuke)
- Hooks return consistent patterns: `{ data, isLoading, error }` or `{ ...data, isLoading, error }`

### Directory Structure for Logic

```
src/
├── lib/
│ ├── api/ # API client and endpoints
│ │ ├── client.ts
│ │ └── endpoints/
│ ├── hooks/ # Custom React hooks
│ │ ├── useOrganization.ts # Org info hook
│ │ ├── usePull.ts # Pull operation hook
│ │ └── index.ts
│ ├── utils/ # Pure utility functions
│ │ └── files.ts
│ └── constants/ # Shared constants, template data
│ └── templates.ts
└── views/react/ # UI components (rendering only)
```

### Example: Good vs Bad

**❌ Bad - Logic in .tsx:**
```tsx
// Component.tsx
export function MyComponent() {
const [data, setData] = useState(null);

useEffect(() => {
async function fetchData() {
const result = await fetch('/api/data');
setData(result);
}
fetchData();
}, []);

return <div>{data}</div>;
}
```

**✅ Good - Logic in hook, .tsx only renders:**
```tsx
// hooks/useMyData.ts
export function useMyData() {
return useQuery({
queryKey: ['myData'],
queryFn: () => fetchMyData(),
});
}

// Component.tsx
export function MyComponent() {
const { data, isLoading, error } = useMyData();

if (isLoading) return <Loading />;
if (error) return <Error message={error.message} />;
return <div>{data}</div>;
}
```
22 changes: 13 additions & 9 deletions atmn/bun.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,29 @@ async function getVersion(): Promise<string> {
}

async function build() {
console.time(`Building atmn v${await getVersion()}`);
const version = await getVersion();

// Build everything with Bun
console.time(`Building atmn v${version}`);
await Bun.build({
entrypoints: ["./source/cli.ts", "./source/index.ts"],
entrypoints: ["./src/cli.tsx", "./source/index.ts"],
outdir: "./dist",
format: "esm",
target: "node",
define: {
VERSION: `"${await getVersion()}"`,
VERSION: `"${version}"`,
},
external: ["prettier"]
external: ["prettier"],
});
console.timeEnd(`Building atmn v${await getVersion()}`);
console.timeEnd(`Building atmn v${version}`);

// Generate TypeScript declaration files
console.time(`Generating TypeScript declaration files`);
await Bun.spawn(["tsc", "--emitDeclarationOnly"], {
// Generate TypeScript declarations with tsc
console.time(`Generating type declarations`);
const tsc = Bun.spawn(["tsc", "--project", "tsconfig.build.json"], {
stdio: ["inherit", "inherit", "inherit"],
});
console.timeEnd(`Generating TypeScript declaration files`);
await tsc.exited;
console.timeEnd(`Generating type declarations`);
}

build();
Loading