fimo 0.3.3-staging.24 → 0.3.4-staging.26
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/README.md +6 -12
- package/assets/agents-starter/AGENTS.md +14 -2
- package/assets/skills/fimo/SKILL.md +1 -1
- package/assets/skills/fimo/references/content.md +14 -2
- package/assets/skills/fimo/references/setup-plain-vite.md +8 -3
- package/assets/skills/fimo/references/setup-react-router.md +13 -6
- package/assets/skills/fimo/references/ui.md +1 -1
- package/assets/skills/fimo-cli/SKILL.md +30 -18
- package/assets/skills/fimo-cli/references/account.md +4 -2
- package/assets/skills/fimo-cli/references/agent-setup.md +14 -16
- package/assets/skills/fimo-cli/references/agents.md +2 -0
- package/assets/skills/fimo-cli/references/analytics.md +2 -0
- package/assets/skills/fimo-cli/references/assets.md +2 -0
- package/assets/skills/fimo-cli/references/branches.md +2 -0
- package/assets/skills/fimo-cli/references/content.md +3 -1
- package/assets/skills/fimo-cli/references/credits.md +2 -0
- package/assets/skills/fimo-cli/references/deploy.md +10 -4
- package/assets/skills/fimo-cli/references/describe.md +2 -0
- package/assets/skills/fimo-cli/references/domains.md +2 -0
- package/assets/skills/fimo-cli/references/forms.md +2 -0
- package/assets/skills/fimo-cli/references/init.md +114 -0
- package/assets/skills/fimo-cli/references/integrations/firecrawl.md +2 -0
- package/assets/skills/fimo-cli/references/integrations.md +2 -0
- package/assets/skills/fimo-cli/references/invite.md +2 -0
- package/assets/skills/fimo-cli/references/labels.md +2 -0
- package/assets/skills/fimo-cli/references/locales.md +2 -0
- package/assets/skills/fimo-cli/references/media.md +2 -0
- package/assets/skills/fimo-cli/references/preview.md +2 -0
- package/assets/skills/fimo-cli/references/project-vars-and-secrets.md +3 -1
- package/assets/skills/fimo-cli/references/projects.md +5 -3
- package/assets/skills/fimo-cli/references/schedules.md +2 -0
- package/assets/skills/fimo-migration/SKILL.md +2 -0
- package/assets/skills/fimo-migration/references/manifest.md +5 -1
- package/dist/build/vite/index.d.ts.map +1 -1
- package/dist/build/vite/index.js +17 -7
- package/dist/cli/bundle.json +1 -1
- package/dist/cli/index.js +2916 -2544
- package/package.json +2 -1
- package/scripts/lib/release-core.mjs +50 -2
- package/scripts/lib/release-core.test.ts +81 -0
- package/scripts/postinstall.mjs +10 -54
- package/scripts/publish-npm.mjs +7 -1
- package/templates/react-router/package.json +1 -1
- package/assets/agents-starter/claude/settings.json +0 -19
- package/assets/skills/fimo-cli/references/create.md +0 -90
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fimo",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4-staging.26",
|
|
4
4
|
"description": "Fimo CLI - create, deploy, and manage Fimo projects",
|
|
5
5
|
"bin": {
|
|
6
6
|
"fimo": "dist/cli/index.js"
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
],
|
|
16
16
|
"type": "module",
|
|
17
17
|
"exports": {
|
|
18
|
+
"./package.json": "./package.json",
|
|
18
19
|
"./ui": {
|
|
19
20
|
"types": "./dist/runtime/index.d.ts",
|
|
20
21
|
"import": "./dist/runtime/index.js"
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
// governs a bare `npm i -g fimo` with no env set. The sandbox always
|
|
11
11
|
// overrides it via the injected `.env`.
|
|
12
12
|
|
|
13
|
-
import { existsSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
14
|
-
import { resolve } from 'node:path';
|
|
13
|
+
import { existsSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
14
|
+
import { join, resolve } from 'node:path';
|
|
15
15
|
|
|
16
16
|
import { ALLOWED_API_URLS } from './channels.mjs';
|
|
17
17
|
|
|
@@ -120,3 +120,51 @@ export function computePublishVersion(baseVersion, channel, opts = {}) {
|
|
|
120
120
|
const n = opts.runId ?? String(Date.now());
|
|
121
121
|
return `${base}-${channel.distTag}.${n}`;
|
|
122
122
|
}
|
|
123
|
+
|
|
124
|
+
const BUMP_RANK = { patch: 1, minor: 2, major: 3 };
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Peek at pending changeset files and compute the version the next
|
|
128
|
+
* `changeset version` run will produce for `fimo`. Prerelease channels use
|
|
129
|
+
* this as their base so a staging build advertises the version prod will
|
|
130
|
+
* actually ship (`0.3.4-staging.26` while 0.3.4 is pending) instead of the
|
|
131
|
+
* already-released base. No pending changesets (or no .changeset dir) →
|
|
132
|
+
* base unchanged.
|
|
133
|
+
*
|
|
134
|
+
* @param {string} baseVersion - package.json version
|
|
135
|
+
* @param {string} changesetDir - absolute path to the repo's .changeset dir
|
|
136
|
+
* @returns {string}
|
|
137
|
+
*/
|
|
138
|
+
export function nextVersionFromChangesets(baseVersion, changesetDir) {
|
|
139
|
+
let entries;
|
|
140
|
+
try {
|
|
141
|
+
entries = readdirSync(changesetDir);
|
|
142
|
+
} catch {
|
|
143
|
+
return baseVersion;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
let maxBump = null;
|
|
147
|
+
for (const name of entries) {
|
|
148
|
+
if (!name.endsWith('.md') || name === 'README.md') {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
const text = readFileSync(join(changesetDir, name), 'utf8');
|
|
152
|
+
const frontmatter = text.match(/^---\n([\s\S]*?)\n---/)?.[1] ?? '';
|
|
153
|
+
const bump = frontmatter.match(/['"]?fimo['"]?\s*:\s*(patch|minor|major)/)?.[1];
|
|
154
|
+
if (bump && (!maxBump || BUMP_RANK[bump] > BUMP_RANK[maxBump])) {
|
|
155
|
+
maxBump = bump;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (!maxBump) {
|
|
160
|
+
return baseVersion;
|
|
161
|
+
}
|
|
162
|
+
const [major, minor, patch] = baseVersion.split('-')[0].split('.').map(Number);
|
|
163
|
+
if (maxBump === 'major') {
|
|
164
|
+
return `${major + 1}.0.0`;
|
|
165
|
+
}
|
|
166
|
+
if (maxBump === 'minor') {
|
|
167
|
+
return `${major}.${minor + 1}.0`;
|
|
168
|
+
}
|
|
169
|
+
return `${major}.${minor}.${patch + 1}`;
|
|
170
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
|
|
5
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
6
|
+
|
|
7
|
+
// @ts-expect-error plain mjs module without types
|
|
8
|
+
import { computePublishVersion, nextVersionFromChangesets } from './release-core.mjs';
|
|
9
|
+
|
|
10
|
+
const stagingChannel = { prerelease: true, distTag: 'staging' };
|
|
11
|
+
const latestChannel = { prerelease: false, distTag: 'latest' };
|
|
12
|
+
|
|
13
|
+
describe('computePublishVersion', () => {
|
|
14
|
+
it('returns the base version verbatim for stable channels', () => {
|
|
15
|
+
expect(computePublishVersion('0.3.3', latestChannel, { runId: '7' })).toBe('0.3.3');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('synthesizes a prerelease version from the run id', () => {
|
|
19
|
+
expect(computePublishVersion('0.3.3', stagingChannel, { runId: '26' })).toBe('0.3.3-staging.26');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('strips an existing prerelease suffix before synthesizing', () => {
|
|
23
|
+
expect(computePublishVersion('0.3.3-staging.9', stagingChannel, { runId: '26' })).toBe('0.3.3-staging.26');
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('nextVersionFromChangesets', () => {
|
|
28
|
+
let dir: string;
|
|
29
|
+
|
|
30
|
+
afterEach(() => {
|
|
31
|
+
if (dir) {
|
|
32
|
+
rmSync(dir, { recursive: true, force: true });
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
function changesetDir(files: Record<string, string>): string {
|
|
37
|
+
dir = mkdtempSync(join(tmpdir(), 'changesets-'));
|
|
38
|
+
writeFileSync(join(dir, 'README.md'), '# Changesets\n');
|
|
39
|
+
for (const [name, frontmatter] of Object.entries(files)) {
|
|
40
|
+
writeFileSync(join(dir, name), `---\n${frontmatter}\n---\n\nsummary\n`);
|
|
41
|
+
}
|
|
42
|
+
return dir;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
it('returns the base when the directory does not exist', () => {
|
|
46
|
+
expect(nextVersionFromChangesets('0.3.3', '/nonexistent/.changeset')).toBe('0.3.3');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('returns the base when no changesets are pending', () => {
|
|
50
|
+
expect(nextVersionFromChangesets('0.3.3', changesetDir({}))).toBe('0.3.3');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('applies a patch bump for pending patch changesets', () => {
|
|
54
|
+
const d = changesetDir({ 'a.md': "'fimo': patch" });
|
|
55
|
+
expect(nextVersionFromChangesets('0.3.3', d)).toBe('0.3.4');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('takes the max bump across pending changesets', () => {
|
|
59
|
+
const d = changesetDir({
|
|
60
|
+
'a.md': "'fimo': patch",
|
|
61
|
+
'b.md': "'fimo': minor",
|
|
62
|
+
'c.md': "'fimo': patch",
|
|
63
|
+
});
|
|
64
|
+
expect(nextVersionFromChangesets('0.3.3', d)).toBe('0.4.0');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('handles major bumps and double-quoted package names', () => {
|
|
68
|
+
const d = changesetDir({ 'a.md': '"fimo": major' });
|
|
69
|
+
expect(nextVersionFromChangesets('0.3.3', d)).toBe('1.0.0');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('ignores changesets for other packages', () => {
|
|
73
|
+
const d = changesetDir({ 'a.md': "'@fimo/fimovm': minor" });
|
|
74
|
+
expect(nextVersionFromChangesets('0.3.3', d)).toBe('0.3.3');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('ignores an existing prerelease suffix on the base', () => {
|
|
78
|
+
const d = changesetDir({ 'a.md': "'fimo': patch" });
|
|
79
|
+
expect(nextVersionFromChangesets('0.3.3-staging.9', d)).toBe('0.3.4');
|
|
80
|
+
});
|
|
81
|
+
});
|
package/scripts/postinstall.mjs
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
// Two paths:
|
|
3
3
|
//
|
|
4
4
|
// 1) GLOBAL install (`npm i -g fimo`, `pnpm add -g fimo`, etc.)
|
|
5
|
-
// →
|
|
6
|
-
//
|
|
5
|
+
// → print a short, non-blocking hint. We steer users toward
|
|
6
|
+
// `npx fimo@latest` (always current) and `fimo init`, and don't run any
|
|
7
|
+
// interactive prompt from a package lifecycle script.
|
|
7
8
|
//
|
|
8
9
|
// 2) LOCAL / project install (`pnpm install` in a project that has `fimo`
|
|
9
10
|
// in its dependencies)
|
|
@@ -17,20 +18,18 @@
|
|
|
17
18
|
// never break the user's install).
|
|
18
19
|
//
|
|
19
20
|
// pnpm caveat: by default, pnpm strips build scripts from non-approved deps.
|
|
20
|
-
// Fimo-controlled installs (`fimo
|
|
21
|
+
// Fimo-controlled installs (`fimo init --install`, sandbox `fimopm install`,
|
|
21
22
|
// and E2E helper installs) pass a scoped allow-all-builds flag for pnpm so the
|
|
22
23
|
// fimo postinstall hook can refresh project skills. The template intentionally
|
|
23
24
|
// does not persist allowlists in package.json / pnpm-workspace.yaml because
|
|
24
25
|
// those conflict with sandbox install flags and drift when deps change. npm /
|
|
25
26
|
// yarn run lifecycle scripts by default and need no extra config.
|
|
26
27
|
|
|
27
|
-
import { spawnSync } from 'node:child_process';
|
|
28
28
|
import fs from 'node:fs';
|
|
29
29
|
import path from 'node:path';
|
|
30
|
-
import readline from 'node:readline/promises';
|
|
31
30
|
import { fileURLToPath } from 'node:url';
|
|
32
31
|
|
|
33
|
-
import { isGlobalInstall
|
|
32
|
+
import { isGlobalInstall } from './lib/postinstall-onboarding.mjs';
|
|
34
33
|
|
|
35
34
|
const THIS_FILE = fileURLToPath(import.meta.url);
|
|
36
35
|
const CLI_ROOT = path.resolve(path.dirname(THIS_FILE), '..');
|
|
@@ -45,22 +44,12 @@ if (isGlobalInstall(process.env)) {
|
|
|
45
44
|
console.log();
|
|
46
45
|
console.log(`${green('✓')} ${bold('fimo')} installed`);
|
|
47
46
|
console.log();
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const shouldInstallSkills = await confirm(`Install Fimo skills for your AI coding tools now? ${dim('[Y/n]')} `);
|
|
51
|
-
if (shouldInstallSkills) {
|
|
52
|
-
await runSkillsInstall();
|
|
53
|
-
} else {
|
|
54
|
-
console.log();
|
|
55
|
-
console.log(` Later: run ${cyan('fimo skills install')} to register Fimo skills.`);
|
|
56
|
-
}
|
|
57
|
-
} else {
|
|
58
|
-
console.log(` Tip: run ${cyan('fimo skills install')} to register Fimo skills`);
|
|
59
|
-
console.log(` for your AI coding tools (Claude Code, Cursor, Codex, ...).`);
|
|
60
|
-
console.log(` ${dim('Skip if you don’t use AI tools.')}`);
|
|
61
|
-
}
|
|
47
|
+
console.log(` Tip: run the latest without a global install:`);
|
|
48
|
+
console.log(` ${cyan('npx fimo@latest <command>')}`);
|
|
62
49
|
console.log();
|
|
63
|
-
console.log(`
|
|
50
|
+
console.log(` Get started:`);
|
|
51
|
+
console.log(` ${cyan('fimo init')} ${dim('# sign in, create or link a project')}`);
|
|
52
|
+
console.log(` ${cyan('fimo skills install')} ${dim('# set up skills for your AI coding tools')}`);
|
|
64
53
|
console.log();
|
|
65
54
|
process.exit(0);
|
|
66
55
|
}
|
|
@@ -97,36 +86,3 @@ try {
|
|
|
97
86
|
console.error('[fimo postinstall] sync failed:', err);
|
|
98
87
|
}
|
|
99
88
|
}
|
|
100
|
-
|
|
101
|
-
async function confirm(message) {
|
|
102
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
103
|
-
try {
|
|
104
|
-
const answer = await rl.question(message);
|
|
105
|
-
return parseYesNo(answer, true);
|
|
106
|
-
} finally {
|
|
107
|
-
rl.close();
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
async function runSkillsInstall() {
|
|
112
|
-
const entry = path.join(CLI_ROOT, 'dist', 'cli', 'index.js');
|
|
113
|
-
if (!fs.existsSync(entry)) {
|
|
114
|
-
console.log();
|
|
115
|
-
console.log(` Run ${cyan('fimo skills install')} after installation finishes.`);
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
console.log();
|
|
120
|
-
const result = spawnSync(process.execPath, [entry, 'skills', 'install', '--yes'], {
|
|
121
|
-
stdio: 'inherit',
|
|
122
|
-
env: {
|
|
123
|
-
...process.env,
|
|
124
|
-
FIMO_POSTINSTALL_CHILD: '1',
|
|
125
|
-
},
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
if (result.error || result.status !== 0) {
|
|
129
|
-
console.log();
|
|
130
|
-
console.log(` Skills were not installed. Run ${cyan('fimo skills install')} to try again.`);
|
|
131
|
-
}
|
|
132
|
-
}
|
package/scripts/publish-npm.mjs
CHANGED
|
@@ -35,6 +35,7 @@ import { resolveChannel } from './lib/channels.mjs';
|
|
|
35
35
|
import { writeDevReleaseState } from './lib/dev-release-state.mjs';
|
|
36
36
|
import {
|
|
37
37
|
computePublishVersion,
|
|
38
|
+
nextVersionFromChangesets,
|
|
38
39
|
pinTemplateFimo,
|
|
39
40
|
stripTemplateLockfile,
|
|
40
41
|
writeReleaseJson,
|
|
@@ -90,7 +91,12 @@ if (channel.distTag === 'latest' && !isCI && !bootstrap) {
|
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
const pkg = JSON.parse(readFileSync(PKG_PATH, 'utf8'));
|
|
93
|
-
|
|
94
|
+
// Prerelease channels base off the version the pending changesets will
|
|
95
|
+
// produce at the next production release, so a staging build advertises the
|
|
96
|
+
// version prod will actually ship.
|
|
97
|
+
const baseVersion = channel.prerelease
|
|
98
|
+
? nextVersionFromChangesets(pkg.version, resolve(CLI_ROOT, '../../.changeset'))
|
|
99
|
+
: pkg.version;
|
|
94
100
|
const runId = process.env.GITHUB_RUN_NUMBER;
|
|
95
101
|
const publishVersion = computePublishVersion(baseVersion, channel, { runId });
|
|
96
102
|
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"Bash(fimo:*)",
|
|
5
|
-
"Bash(npx fimo:*)",
|
|
6
|
-
"Bash(pnpm:*)",
|
|
7
|
-
"Bash(pnpm dlx:*)",
|
|
8
|
-
"Bash(npx:*)",
|
|
9
|
-
"Bash(git status)",
|
|
10
|
-
"Bash(git status:*)",
|
|
11
|
-
"Bash(git diff)",
|
|
12
|
-
"Bash(git diff:*)",
|
|
13
|
-
"Bash(git log:*)",
|
|
14
|
-
"Bash(git add:*)",
|
|
15
|
-
"Bash(git restore:*)",
|
|
16
|
-
"Bash(mkdir:*)"
|
|
17
|
-
]
|
|
18
|
-
}
|
|
19
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
# `fimo create`
|
|
2
|
-
|
|
3
|
-
Scaffold a new Fimo project linked to a remote on the Fimo platform.
|
|
4
|
-
|
|
5
|
-
## Command
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
fimo create [dir] [options]
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
| Flag | Required | Purpose |
|
|
12
|
-
| ---------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
13
|
-
| `[dir]` positional | yes in non-TTY | Target directory (e.g. `my-site`) |
|
|
14
|
-
| `--org <id>` | yes in non-TTY | Target organization **id** (use the `ID` column from `fimo orgs list`, NOT the slug). Picker shown interactively if omitted and TTY. |
|
|
15
|
-
| `--install` / `--no-install` | yes in non-TTY | Run `pnpm install` after scaffolding (or skip it). |
|
|
16
|
-
| `--agents <list>` | yes in non-TTY | Comma-separated agent IDs (e.g. `claude-code,cursor`). Pass `none` to write only universal AGENTS.md. |
|
|
17
|
-
| `-a, --agent <id>` | alternative | Repeatable form: `-a claude-code -a cursor`. |
|
|
18
|
-
| `--template-root <path>` | no | Override the bundled template (development only). |
|
|
19
|
-
|
|
20
|
-
Without the required flags in a non-TTY shell, the command exits with `Cannot prompt in a non-interactive shell.`
|
|
21
|
-
|
|
22
|
-
For `--agents`, pass the AI tool you're running in: `--agents=claude-code` for Claude Code, `--agents=cursor` for Cursor, `--agents=codex` for Codex, etc. When the flag is omitted, env-var detection of the invoking harness (e.g. `CLAUDECODE` / `CLAUDE_CODE_ENTRYPOINT` → claude-code) auto-targets that agent; other agents must be selected explicitly via `--agents`/`-a` or the interactive picker.
|
|
23
|
-
|
|
24
|
-
## What gets written
|
|
25
|
-
|
|
26
|
-
`fimo create` scaffolds:
|
|
27
|
-
|
|
28
|
-
- The project template (Vite + React 19 + TypeScript + Tailwind v4 + shadcn/ui + react-router)
|
|
29
|
-
- `.fimo.settings.json` — links this directory to the remote project (read-only after creation)
|
|
30
|
-
- `.env` — initial env vars (currently just `VITE_API_URL`)
|
|
31
|
-
- `AGENTS.md` — project rules read by all agentskills.io-compatible AI tools (Codex, OpenCode, Aider, etc.)
|
|
32
|
-
- Per-agent variants based on `--agents`:
|
|
33
|
-
- `claude-code` → `CLAUDE.md` + `.claude/settings.json`
|
|
34
|
-
- `cursor` → `.cursor/rules/fimo.mdc`
|
|
35
|
-
- `windsurf` → `.windsurfrules`
|
|
36
|
-
- `gemini-cli` → `GEMINI.md`
|
|
37
|
-
- codex / opencode / aider / others → no extra file; AGENTS.md is read natively
|
|
38
|
-
- The project-scope `fimo` skill (npm package surface: schemas, forms, `t()`, `fimo/ui` components) copied into each selected agent's skill dir (`.claude/skills/fimo/`, `.cursor/skills/fimo/`, etc.). Version-locked to the bundled `fimo` package — the installed `SKILL.md` is stamped with `fimoVersion`. Refresh later with `fimo skills sync`. See `references/agent-setup.md`.
|
|
39
|
-
- A git repository with `fimo` as the remote, an initial commit, and an initial push
|
|
40
|
-
|
|
41
|
-
Codex, OpenCode, Aider, and similar AGENTS.md-native tools work directly off AGENTS.md without a per-agent variant.
|
|
42
|
-
|
|
43
|
-
`.env` is only the bootstrap app env so local `pnpm dev` works immediately. User-managed public variables are stored with `fimo vars set` and synced into a managed `.env.local` block; hidden values use `fimo secrets set`. See `references/project-vars-and-secrets.md`.
|
|
44
|
-
|
|
45
|
-
## Right after scaffolding
|
|
46
|
-
|
|
47
|
-
Set a human-readable display name with `fimo rename "<Name>"`. Infer it from what the user is building (e.g. "Acme Coffee" for a café site, "Jane Doe Portfolio" for a personal site). The default post-`fimo create` name is an auto-generated slug; renaming updates the dashboard label and the SEO `siteName`.
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
cd my-site
|
|
51
|
-
fimo rename "Acme Coffee"
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
**Then kick off a warm-up deploy in the background** so the sandbox provisions and installs the user's deps (which may differ from the template's baked ones) while you generate code. The first deploy of a project's life pays a ~15-30s provisioning cost; doing it in the background means the user's first interactive deploy lands on a warm sandbox and finishes in ~4-10s instead. See `references/deploy.md` § Warm the sandbox early in a session.
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
fimo deploy -m "chore: init" &
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
`-m` is the commit message for any files `validate` may codegen — use a sensible conventional-commit string (e.g. `chore: init`, `chore: scaffold`).
|
|
61
|
-
|
|
62
|
-
## Load the project context
|
|
63
|
-
|
|
64
|
-
After `fimo create` completes, the project root has:
|
|
65
|
-
|
|
66
|
-
- `AGENTS.md` (universal) plus the per-agent variant for the AI tool you're running in (e.g. `CLAUDE.md` for Claude Code, `.cursor/rules/fimo.mdc` for Cursor)
|
|
67
|
-
- `.claude/skills/fimo/SKILL.md` (or the equivalent per-agent path) — the project-scope `fimo` skill, version-locked to the installed `fimo` package
|
|
68
|
-
|
|
69
|
-
**These files came into existence mid-session, so they may not be auto-loaded by the harness.** Explicitly:
|
|
70
|
-
|
|
71
|
-
1. `cd <project-dir>` — switch into the new project.
|
|
72
|
-
2. `Read` the project rules file: `AGENTS.md` (or `CLAUDE.md` if you're Claude Code).
|
|
73
|
-
3. `Read` the project skill: `.claude/skills/fimo/SKILL.md` (or `.cursor/skills/fimo/SKILL.md` for Cursor, etc.).
|
|
74
|
-
4. From the project skill's "load these references up front" section, batch-read `references/content.md`, `references/forms.md`, `references/assets.md`, `references/labels.md`, `references/locales.md`, `references/ui.md` before generating any significant code.
|
|
75
|
-
|
|
76
|
-
Once those are in context, generation respects the project's conventions (schemas, `t()`, `fimo/ui` components, asset handling).
|
|
77
|
-
|
|
78
|
-
## Adding another AI tool to an existing project later
|
|
79
|
-
|
|
80
|
-
If a teammate joins on a different AI tool (e.g. Cursor) after the project was scaffolded for claude-code only:
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
fimo skills install --agents=cursor # one command — global skill + project skill + rule file
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
Run from inside the project. The command detects the project context and wires up everything for the new agent in a single shot. See `references/agent-setup.md`.
|
|
87
|
-
|
|
88
|
-
## Multi-org accounts
|
|
89
|
-
|
|
90
|
-
If you belong to a single organization, `fimo create` defaults to it. If you belong to multiple and don't pass `--org`, the CLI shows an interactive picker. For `fimo create`, pass the org **id** (from the `ID` column of `fimo orgs list`) — not the slug. Use `fimo orgs switch --org <id-or-slug>` to set a default for future `fimo create` invocations. See `references/account.md`.
|