用 AtomCode 从零开发并部署上线:一个 Flask 待办应用的完整实战

本文是一篇全程真机实操的记录。所有命令、输出、HTTP 状态码、Git 提交与仓库地址均来自服务器 117.72.182.3(Ubuntu 22.04 / Python 3.10.12)上的真实执行,非示意。

目标:只给 AtomCode 一句需求,让它从零写出一个可运行的 Flask 任务管理应用,然后在服务器上部署上线推送到全新的 Gitee 仓库

  • 编程执行引擎:AtomCode 4.26.0(模型 deepseek-v4-flash
  • 最终成果仓库:https://gitee.com/LiaCin/atomcode-flask-todo

目录


一、这篇文章要证明什么

一句话:从一句需求到线上可访问的服务 + 云端代码仓库,全程由 AtomCode 自动完成编码,人只负责"下需求、验收、上线"。

拆成 6 个可验证的步骤:

步骤 做什么 由谁完成 验收凭证
1 写需求(prompt.txt) 见 §四
2 从零生成全部代码 AtomCode 见 §五、§六
3 自测 AtomCode 自跑 + 人复跑 18 tests OK(§七)
4 部署运行 curl 200/201(§八)
5 新建远程仓库 人(Gitee API) HTTP 201(§九)
6 推送代码 人(git push) new branch main(§九)

二、整体流程一图看懂

① 写需求 prompt.txt
REST+SQLite+前端+测试

② atomcode -y --prompt-file
headless 自动开发

③ AtomCode 生成 8 个文件
app.py / static/* / test_app.py / README ...

④ python3 test_app.py
18 tests OK

⑤ nohup python3 app.py
监听 0.0.0.0:5000

⑥ curl 验收
health 200 / create 201 / list 200

⑦ Gitee API 新建仓库
HTTP 201

⑧ git init/commit/push
main -> origin

✅ 线上服务 + 云端仓库
gitee.com/LiaCin/atomcode-flask-todo

核心分工:AtomCode 负责 ②③(写代码 + 自测),人负责 ①④⑤⑥⑦⑧(下需求、验收、部署、建仓、推送)。


三、环境准备

服务器实测环境:

OS      : Ubuntu 22.04(内核容器/云主机)
Python  : Python 3.10.12
pip     : pip 22.0.2
Flask   : 3.1.3(已装)
AtomCode: 4.26.0  (/usr/local/bin/atomcode,Rust 二进制)
模型     : deepseek-v4-flash(base_url = https://llm-api.atomgit.com/v1)
工作目录 : /root/projects/flask-todo

AtomCode 是 Rust 单二进制,不依赖 Node 运行时;官方一键安装:
curl -fsSL https://raw.atomgit.com/.../install.sh | sh


四、第 1 步:写清楚需求(Prompt 即规格)

AtomCode 的产出质量,几乎完全取决于需求写得有多具体。这里把需求当"规格说明书"写进 prompt.txt,明确到接口、字段、端口、文件清单

You are an expert software engineer. Build a complete, runnable Flask
task-management web application in /root/projects/flask-todo.

1. Backend (app.py):
   - Flask only, SQLite (tasks.db),tasks 表:id/title/description/done/created_at
   - REST API:
       GET    /api/health      -> {"status":"ok"}
       GET    /api/tasks       -> 全部任务(最新在前)
       POST   /api/tasks       -> 创建(JSON title/description),返回 201
       GET    /api/tasks/<id>  -> 单条或 404
       PUT    /api/tasks/<id>  -> 更新,返回更新后对象
       DELETE /api/tasks/<id>  -> 删除,返回 204
   - static/ 目录托管前端;默认监听 127.0.0.1:5000(env PORT 可覆盖;后续为对外访问已改为 0.0.0.0,见 §8.1)
   - 启动时自建表;if __name__ == "__main__" 守卫
2. Frontend (static/index.html + app.js + style.css):原生 fetch,无框架
3. requirements.txt: 仅 flask
4. README.md:运行说明 + 接口表
5. test_app.py:用 Flask test client 建任务并断言其出现,可 python3 直接跑

Keep everything local; do NOT expose the server publicly.

经验:接口用"方法 + 路径 + 期望状态码"三元组写死,AtomCode 就不会自由发挥出你不想要的路由。


五、第 2 步:一条命令让 AtomCode 从零开发

用 headless(非交互)模式,让 AtomCode 读需求文件、自动写代码、自动自测:

cd /root/projects/flask-todo
atomcode -y \
  -C /root/projects/flask-todo \
  --max-turns 30 \
  --prompt-file /root/projects/flask-todo/prompt.txt \
  --disable-tools none \
  > build.log 2>&1

参数拆解:

参数 作用
-y / --dangerously-skip-permissions 自动批准所有工具调用(无人值守必需)
-C <dir> 指定工作目录,代码就地生成
--max-turns 30 最多 30 个自主回合,防止跑飞
--prompt-file 从文件读需求(比 -p 更适合长规格)
--disable-tools none 允许全部工具(读写文件、跑 bash、跑测试)

build.log 里 AtomCode 的自述(真实节选):

[engine v2] new stack active (model deepseek-v4-flash)
[headless] --dangerously-skip-permissions: all tool calls are auto-approved
...
All 18 tests pass. Let me clean up the temp database file ... and finalize.
All tasks complete. Here's a summary of the project:

也就是说,AtomCode 自己写完代码后,自己跑了 18 个测试并全部通过,才宣布收工。


六、第 3 步:AtomCode 交付了什么

find 实测生成的文件清单:

/root/projects/flask-todo/app.py            # Flask 后端(REST + SQLite + 静态托管)
/root/projects/flask-todo/static/index.html # 单页前端
/root/projects/flask-todo/static/app.js     # 原生 fetch CRUD
/root/projects/flask-todo/static/style.css  # 响应式样式
/root/projects/flask-todo/test_app.py       # 18 个 API 测试
/root/projects/flask-todo/requirements.txt  # 仅 flask
/root/projects/flask-todo/README.md         # 运行说明 + 接口表
/root/projects/flask-todo/build.log         # AtomCode 自述日志

AtomCode 生成的接口一览(与需求完全对齐):

Method Path 动作 状态码
GET /api/health 健康检查 200
GET /api/tasks 列出全部(最新在前) 200
POST /api/tasks 创建任务 201
GET /api/tasks/<id> 查单条 200 / 404
PUT /api/tasks/<id> 更新 200
DELETE /api/tasks/<id> 删除 204

七、第 4 步:跑测试(18 个用例)

人工复跑一遍 AtomCode 写的测试,验证不是"自说自话":

cd /root/projects/flask-todo && python3 test_app.py

真实输出(尾部):

test_get_task ... ok
test_get_task_not_found ... ok
test_health ... ok
test_list_tasks_empty ... ok
test_list_tasks_order ... ok
test_update_task_done ... ok
test_update_task_invalid_done ... ok
test_update_task_not_found ... ok
test_update_task_title ... ok
----------------------------------------------------------------------
Ran 18 tests in 0.133s

OK

覆盖:健康检查、完整 CRUD、参数校验(缺 title / done 非法值)、404 分支、列表排序、静态文件托管。18/18 通过。


八、第 5 步:部署上线 + curl 验收

后台启动服务(干净库,重定向日志):

cd /root/projects/flask-todo
rm -f tasks.db
nohup python3 app.py > /tmp/flask.out 2>&1 &

启动日志(真实,绑定 0.0.0.0 后):

 * Serving Flask app 'app'
 * Debug mode: on
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
 * Running on http://172.16.0.3:5000
 * Debugger is active!

端口确认在听(已绑定到全部网卡 0.0.0.0):

$ ss -ltnp | grep 5000
LISTEN 0 128 0.0.0.0:5000 ... users:(("python3",pid=27836,...))

验收 1|健康检查:

$ curl -s -w '\n[HTTP %{http_code}]\n' http://127.0.0.1:5000/api/health
{ "status": "ok" }
[HTTP 200]

验收 2|创建任务(中文入参):

$ curl -s -X POST http://127.0.0.1:5000/api/tasks \
    -H 'Content-Type: application/json' \
    -d '{"title":"部署验收任务","description":"AtomCode 从零开发并上线"}'
{
  "created_at": "2026-07-10T09:38:46.063850+00:00",
  "description": "AtomCode 从零开发并上线",
  "done": 0,
  "id": 1,
  "title": "部署验收任务"
}
[HTTP 201]

验收 3|列表回读:

$ curl -s http://127.0.0.1:5000/api/tasks
[ { "id": 1, "title": "部署验收任务", "done": 0, ... } ]
[HTTP 200]

验收 4|前端首页:

$ curl -s -o /dev/null -w 'index.html [HTTP %{http_code}] %{size_download} bytes\n' http://127.0.0.1:5000/
index.html [HTTP 200] 891 bytes

至此,服务已在服务器上真实运行并对外提供 REST + 前端页面

8.1 改为对外监听 0.0.0.0(公网可访问)

默认 app.py 写的是 host="127.0.0.1",只能本机 127.0.0.1 访问。若要让服务对外部网络开放,只需把启动地址改成 0.0.0.0

# app.py 第 174-176 行
host = "0.0.0.0"                 # 原为 "127.0.0.1"
port = int(os.environ.get("PORT", 5000))
app.run(host=host, port=port, debug=True)

改完重启并复验(真实输出):

$ ss -ltnp | grep 5000
LISTEN 0 128 0.0.0.0:5000 ... users:(("python3",pid=27836,...))

$ curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:5000/api/health
200
$ curl -s -o /dev/null -w '%{http_code}\n' http://0.0.0.0:5000/api/health
200

外部可达性还需两步(本次已确认服务器内部 0.0.0.0 绑定成功,但公网探测返回 000):

检查项 状态 说明
服务绑定 0.0.0.0:5000 ✅ 已生效 ss 明确看到 0.0.0.0:5000
云安全组 / 防火墙放通 5000 ⚠️ 需手动 本机 curl 117.72.182.3:5000000,需在云控制台入站规则放行 TCP 5000
本机公网 IP 117.72.182.3 外部访问地址即 http://117.72.182.3:5000

改完记得把代码推回仓库:git commit -m 'chore: bind 0.0.0.0:5000 for external access' && git push(实际已推,commit a84c9b4)。

⚠️ 安全红线debug=True 的开发服务器一旦绑定 0.0.0.0 暴露到公网,Werkzeug 调试器存在**远程代码执行(RCE)**风险(知道 PIN 或绕过 PIN 即可执行任意命令)。公网开放务必关 debug,见下方生产建议。

生产建议:app.run(debug=True) 仅用于本次验收;正式上线应换 gunicorn -w 4 -b 127.0.0.1:5000 app:app + Nginx 反代(Nginx 监听 0.0.0.0:80/443 对外,Flask 仍只绑内网),并关闭 debug。若确实要 Flask 直连公网,至少 debug=False 且加反向代理与访问控制。


九、第 6 步:推送到全新 Gitee 仓库

9.1 用 Gitee API 新建仓库

curl -s -X POST 'https://gitee.com/api/v5/user/repos' \
  -H 'Content-Type: application/json' \
  -d '{"access_token":"<TOKEN>","name":"atomcode-flask-todo",
       "description":"由 AtomCode 从零自动开发的 Flask 任务管理应用",
       "private":false,"has_issues":true}'

返回(真实,节选):

{ "full_name": "LiaCin/atomcode-flask-todo",
  "html_url": "https://gitee.com/LiaCin/atomcode-flask-todo.git",
  "private": true }
[HTTP 201]

⚠️ 注意:即使传 private:false,Gitee 新建仓库默认仍为私有,需要公开可到仓库设置里手动改。

9.2 加 .gitignore(别把库/日志/凭据提交上去)

__pycache__/
*.pyc
tasks.db
build.log
prompt.txt
*.out
.venv/

9.3 配置 Git 身份并提交

该服务器原本没有全局 Git 身份(/root/.gitconfig 不存在),首次提交前必须配置:

git config --global user.name  "LiaCin"
git config --global user.email "liacin@gitee.com"
git config --global init.defaultBranch main

cd /root/projects/flask-todo
git init
git add -A
git commit -m "feat: AtomCode 从零生成的 Flask 待办应用(REST API + SQLite + 原生JS前端 + 18测试)"

提交结果(真实):

2deaf20 feat: AtomCode 从零生成的 Flask 待办应用...
---tracked files---
.gitignore
README.md
app.py
requirements.txt
static/app.js
static/index.html
static/style.css
test_app.py

9.4 推送

# 用 token 临时鉴权:https://<用户名>:<TOKEN>@gitee.com/<owner>/<repo>.git
git remote add origin "https://LiaCin:<TOKEN>@gitee.com/LiaCin/atomcode-flask-todo.git"
git branch -M main
git push -u origin main

推送结果(真实):

To https://gitee.com/LiaCin/atomcode-flask-todo.git
 * [new branch]      main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.

API 二次核验 default_branch 已变为 main

$ curl -s 'https://gitee.com/api/v5/repos/LiaCin/atomcode-flask-todo?access_token=<TOKEN>'
... "default_branch":"main" ...
[HTTP 200]

🎉 代码已上云:https://gitee.com/LiaCin/atomcode-flask-todo


十、安全收尾

真机操作后必须做的收尾(本次已全部执行):

  1. 清除 remote 里的明文 token——push 完把带 token 的 URL 换掉:
    git remote set-url origin https://gitee.com/LiaCin/atomcode-flask-todo.git
    
    核验:git remote -v 已不含 token。
  2. 停掉验收用的 debug 服务pkill -f 'python3 app.py'
  3. 删除本地含明文凭据的临时脚本(root 密码 / Gitee token 均不落盘)。
  4. 敏感文件进 .gitignoretasks.dbbuild.logprompt.txt*.out 不入库。

十一、关键命令速查表

阶段 命令
让 AtomCode 开发 atomcode -y -C <dir> --max-turns 30 --prompt-file prompt.txt --disable-tools none
复跑测试 python3 test_app.py
后台起服务 nohup python3 app.py > /tmp/flask.out 2>&1 &
查端口 ss -ltnp | grep 5000
健康检查 curl -s http://0.0.0.0:5000/api/health(或 127.0.0.1
开放公网 app.run(host="0.0.0.0") + 云安全组放行 5000
建 Gitee 仓库 curl -X POST gitee.com/api/v5/user/repos -d '{"access_token":"..","name":".."}'
Git 身份 git config --global user.name/user.email
首推 git init && git add -A && git commit -m .. && git push -u origin main
清 token git remote set-url origin https://gitee.com/<owner>/<repo>.git

十二、踩坑与经验

现象 解决
Gitee token 校验用错方式 Bearer 头 → 401 Gitee 用 ?access_token= 查询参数或 Authorization: token
owner 用了显示名 Lincoln/xxx → 404 path LiaCin(显示名 name ≠ 仓库 owner path)
新仓库默认私有 private:false 仍是私有 到仓库设置手动改公开
服务器无 Git 身份 commit 报 author unknown git config --global user.name/email
token 写进 remote 明文残留在 .git/config push 后立即 git remote set-url 去掉 token
headless 权限 交互确认卡住 无人值守用 -y,并配 --max-turns 兜底
需求太笼统 生成的路由/字段跑偏 prompt 里把"方法+路径+状态码+字段"写死

最大的一条经验:把 prompt.txt 当成给资深工程师的验收标准来写——你写得越像规格说明书,AtomCode 一次成型的概率越高。这次 18 个测试全过、6 个接口零返工,靠的就是需求写得够死。


十三、附录:AtomCode 生成的核心代码

app.py(AtomCode 自动生成,未经人工改动,节选主体):

#!/usr/bin/env python3
"""Flask task-management API with SQLite backend."""
import os, sqlite3
from datetime import datetime, timezone
from flask import Flask, g, jsonify, request, send_from_directory

app = Flask(__name__, static_folder="static")
DATABASE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "tasks.db")

def get_db():
    if "db" not in g:
        g.db = sqlite3.connect(DATABASE)
        g.db.row_factory = sqlite3.Row
    return g.db

def init_db():
    with app.app_context():
        db = get_db()
        db.execute("""
            CREATE TABLE IF NOT EXISTS tasks (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                title TEXT NOT NULL, description TEXT,
                done INTEGER NOT NULL DEFAULT 0, created_at TEXT NOT NULL)""")
        db.commit()

@app.route("/api/health")
def api_health():
    return jsonify({"status": "ok"})

@app.route("/api/tasks", methods=["POST"])
def api_create_task():
    data = request.get_json(silent=True)
    if not data or not data.get("title", "").strip():
        return jsonify({"error": "title is required"}), 400
    title = data["title"].strip()
    description = data.get("description", "").strip() or None
    now = datetime.now(timezone.utc).isoformat()
    db = get_db()
    cur = db.execute(
        "INSERT INTO tasks (title, description, done, created_at) VALUES (?,?,0,?)",
        (title, description, now))
    db.commit()
    task = db.execute("SELECT * FROM tasks WHERE id=?", (cur.lastrowid,)).fetchone()
    return jsonify(dict(task)), 201

# ... GET/PUT/DELETE /api/tasks/<id>、静态托管路由略(结构同上)...

if __name__ == "__main__":
    init_db()
    port = int(os.environ.get("PORT", 5000))
    app.run(host="0.0.0.0", port=port, debug=True)   # 已改为对外监听;生产环境应 debug=False

亮点(全部由 AtomCode 自主决定):

  • g + teardown_appcontext 管理 SQLite 连接,请求级复用、自动关闭;
  • PUT 更新做了类型与取值校验done 只允许 0/1,title 必须字符串);
  • created_at 用带时区的 ISO8601;列表按 created_at DESC 排序;
  • 入口 init_db() 幂等建表,端口支持 PORT 环境变量覆盖。

一句话总结:需求写进一个文件 → atomcode -y --prompt-file 一条命令 → 8 个文件 + 18 个通过的测试自动生成 → curl 验收 200/201 → Gitee 建仓 + git push 上云。人只做了"下需求、验收、上线",写代码这件事,AtomCode 全包了。

成果仓库:https://gitee.com/LiaCin/atomcode-flask-todo

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐